blob: d118ffe0bfb6edbd46aa634dc3750edb0fd235bf [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
Ismail, Mustafa19655362017-07-14 09:41:30 -05002345 if ((cmd.attr_mask & IB_QP_PORT) &&
2346 (cmd.port_num < rdma_start_port(ib_dev) ||
2347 cmd.port_num > rdma_end_port(ib_dev)))
Boris Pismenny84b00cd2017-06-27 15:09:13 +03002348 return -EINVAL;
2349
Ralph Campbell9bc57e22006-08-11 14:58:09 -07002350 INIT_UDATA(&udata, buf + sizeof cmd, NULL, in_len - sizeof cmd,
2351 out_len);
2352
Roland Dreierbc38a6a2005-07-07 17:57:13 -07002353 attr = kmalloc(sizeof *attr, GFP_KERNEL);
2354 if (!attr)
2355 return -ENOMEM;
2356
Roland Dreier9ead1902006-06-17 20:44:49 -07002357 qp = idr_read_qp(cmd.qp_handle, file->ucontext);
2358 if (!qp) {
Roland Dreierbc38a6a2005-07-07 17:57:13 -07002359 ret = -EINVAL;
2360 goto out;
2361 }
2362
2363 attr->qp_state = cmd.qp_state;
2364 attr->cur_qp_state = cmd.cur_qp_state;
2365 attr->path_mtu = cmd.path_mtu;
2366 attr->path_mig_state = cmd.path_mig_state;
2367 attr->qkey = cmd.qkey;
2368 attr->rq_psn = cmd.rq_psn;
2369 attr->sq_psn = cmd.sq_psn;
2370 attr->dest_qp_num = cmd.dest_qp_num;
2371 attr->qp_access_flags = cmd.qp_access_flags;
2372 attr->pkey_index = cmd.pkey_index;
Ami Perlmutter702b2aa2006-03-20 10:08:24 -08002373 attr->alt_pkey_index = cmd.alt_pkey_index;
Roland Dreierbc38a6a2005-07-07 17:57:13 -07002374 attr->en_sqd_async_notify = cmd.en_sqd_async_notify;
2375 attr->max_rd_atomic = cmd.max_rd_atomic;
2376 attr->max_dest_rd_atomic = cmd.max_dest_rd_atomic;
2377 attr->min_rnr_timer = cmd.min_rnr_timer;
2378 attr->port_num = cmd.port_num;
2379 attr->timeout = cmd.timeout;
2380 attr->retry_cnt = cmd.retry_cnt;
2381 attr->rnr_retry = cmd.rnr_retry;
2382 attr->alt_port_num = cmd.alt_port_num;
2383 attr->alt_timeout = cmd.alt_timeout;
2384
2385 memcpy(attr->ah_attr.grh.dgid.raw, cmd.dest.dgid, 16);
2386 attr->ah_attr.grh.flow_label = cmd.dest.flow_label;
2387 attr->ah_attr.grh.sgid_index = cmd.dest.sgid_index;
2388 attr->ah_attr.grh.hop_limit = cmd.dest.hop_limit;
2389 attr->ah_attr.grh.traffic_class = cmd.dest.traffic_class;
2390 attr->ah_attr.dlid = cmd.dest.dlid;
2391 attr->ah_attr.sl = cmd.dest.sl;
2392 attr->ah_attr.src_path_bits = cmd.dest.src_path_bits;
2393 attr->ah_attr.static_rate = cmd.dest.static_rate;
2394 attr->ah_attr.ah_flags = cmd.dest.is_global ? IB_AH_GRH : 0;
2395 attr->ah_attr.port_num = cmd.dest.port_num;
2396
2397 memcpy(attr->alt_ah_attr.grh.dgid.raw, cmd.alt_dest.dgid, 16);
2398 attr->alt_ah_attr.grh.flow_label = cmd.alt_dest.flow_label;
2399 attr->alt_ah_attr.grh.sgid_index = cmd.alt_dest.sgid_index;
2400 attr->alt_ah_attr.grh.hop_limit = cmd.alt_dest.hop_limit;
2401 attr->alt_ah_attr.grh.traffic_class = cmd.alt_dest.traffic_class;
2402 attr->alt_ah_attr.dlid = cmd.alt_dest.dlid;
2403 attr->alt_ah_attr.sl = cmd.alt_dest.sl;
2404 attr->alt_ah_attr.src_path_bits = cmd.alt_dest.src_path_bits;
2405 attr->alt_ah_attr.static_rate = cmd.alt_dest.static_rate;
2406 attr->alt_ah_attr.ah_flags = cmd.alt_dest.is_global ? IB_AH_GRH : 0;
2407 attr->alt_ah_attr.port_num = cmd.alt_dest.port_num;
2408
Sean Hefty0e0ec7e2011-08-08 15:31:51 -07002409 if (qp->real_qp == qp) {
Matan Barakdbf727d2015-10-15 18:38:51 +03002410 ret = ib_resolve_eth_dmac(qp, attr, &cmd.attr_mask);
Or Gerlitzed4c54e2013-12-12 18:03:17 +02002411 if (ret)
Moshe Lazer0fb8bcf2015-02-05 13:53:52 +02002412 goto release_qp;
Sean Hefty0e0ec7e2011-08-08 15:31:51 -07002413 ret = qp->device->modify_qp(qp, attr,
2414 modify_qp_mask(qp->qp_type, cmd.attr_mask), &udata);
2415 } else {
2416 ret = ib_modify_qp(qp, attr, modify_qp_mask(qp->qp_type, cmd.attr_mask));
2417 }
Roland Dreier9ead1902006-06-17 20:44:49 -07002418
Roland Dreierbc38a6a2005-07-07 17:57:13 -07002419 if (ret)
Moshe Lazer0fb8bcf2015-02-05 13:53:52 +02002420 goto release_qp;
Roland Dreierbc38a6a2005-07-07 17:57:13 -07002421
2422 ret = in_len;
2423
Moshe Lazer0fb8bcf2015-02-05 13:53:52 +02002424release_qp:
2425 put_qp_read(qp);
2426
Roland Dreierbc38a6a2005-07-07 17:57:13 -07002427out:
Roland Dreierbc38a6a2005-07-07 17:57:13 -07002428 kfree(attr);
2429
2430 return ret;
2431}
2432
2433ssize_t ib_uverbs_destroy_qp(struct ib_uverbs_file *file,
Yishai Hadas057aec02015-08-13 18:32:04 +03002434 struct ib_device *ib_dev,
Roland Dreierbc38a6a2005-07-07 17:57:13 -07002435 const char __user *buf, int in_len,
2436 int out_len)
2437{
Roland Dreier63aaf642005-09-09 15:55:08 -07002438 struct ib_uverbs_destroy_qp cmd;
2439 struct ib_uverbs_destroy_qp_resp resp;
Roland Dreier9ead1902006-06-17 20:44:49 -07002440 struct ib_uobject *uobj;
Roland Dreier63aaf642005-09-09 15:55:08 -07002441 struct ib_qp *qp;
Roland Dreier9ead1902006-06-17 20:44:49 -07002442 struct ib_uqp_object *obj;
Roland Dreier63aaf642005-09-09 15:55:08 -07002443 int ret = -EINVAL;
Roland Dreierbc38a6a2005-07-07 17:57:13 -07002444
2445 if (copy_from_user(&cmd, buf, sizeof cmd))
2446 return -EFAULT;
2447
Roland Dreier63aaf642005-09-09 15:55:08 -07002448 memset(&resp, 0, sizeof resp);
2449
Roland Dreier9ead1902006-06-17 20:44:49 -07002450 uobj = idr_write_uobj(&ib_uverbs_qp_idr, cmd.qp_handle, file->ucontext);
2451 if (!uobj)
2452 return -EINVAL;
2453 qp = uobj->object;
2454 obj = container_of(uobj, struct ib_uqp_object, uevent.uobject);
Roland Dreierbc38a6a2005-07-07 17:57:13 -07002455
Roland Dreier9ead1902006-06-17 20:44:49 -07002456 if (!list_empty(&obj->mcast_list)) {
2457 put_uobj_write(uobj);
2458 return -EBUSY;
Jack Morgensteinf4e40152005-11-29 16:57:01 -08002459 }
Roland Dreierbc38a6a2005-07-07 17:57:13 -07002460
2461 ret = ib_destroy_qp(qp);
Roland Dreier9ead1902006-06-17 20:44:49 -07002462 if (!ret)
2463 uobj->live = 0;
Roland Dreierbc38a6a2005-07-07 17:57:13 -07002464
Roland Dreier9ead1902006-06-17 20:44:49 -07002465 put_uobj_write(uobj);
2466
2467 if (ret)
2468 return ret;
2469
Yishai Hadas846be902013-08-01 18:49:54 +03002470 if (obj->uxrcd)
2471 atomic_dec(&obj->uxrcd->refcnt);
2472
Roland Dreier9ead1902006-06-17 20:44:49 -07002473 idr_remove_uobj(&ib_uverbs_qp_idr, uobj);
Roland Dreierbc38a6a2005-07-07 17:57:13 -07002474
Ingo Molnar95ed6442006-01-13 14:51:39 -08002475 mutex_lock(&file->mutex);
Roland Dreier9ead1902006-06-17 20:44:49 -07002476 list_del(&uobj->list);
Ingo Molnar95ed6442006-01-13 14:51:39 -08002477 mutex_unlock(&file->mutex);
Roland Dreierbc38a6a2005-07-07 17:57:13 -07002478
Roland Dreier9ead1902006-06-17 20:44:49 -07002479 ib_uverbs_release_uevent(file, &obj->uevent);
Roland Dreier63aaf642005-09-09 15:55:08 -07002480
Roland Dreier9ead1902006-06-17 20:44:49 -07002481 resp.events_reported = obj->uevent.events_reported;
Roland Dreier63aaf642005-09-09 15:55:08 -07002482
Roland Dreier9ead1902006-06-17 20:44:49 -07002483 put_uobj(uobj);
Roland Dreierbc38a6a2005-07-07 17:57:13 -07002484
Roland Dreier63aaf642005-09-09 15:55:08 -07002485 if (copy_to_user((void __user *) (unsigned long) cmd.response,
2486 &resp, sizeof resp))
Roland Dreier9ead1902006-06-17 20:44:49 -07002487 return -EFAULT;
Roland Dreier63aaf642005-09-09 15:55:08 -07002488
Roland Dreier9ead1902006-06-17 20:44:49 -07002489 return in_len;
Roland Dreierbc38a6a2005-07-07 17:57:13 -07002490}
2491
Christoph Hellwige622f2f2015-10-08 09:16:33 +01002492static void *alloc_wr(size_t wr_size, __u32 num_sge)
2493{
2494 return kmalloc(ALIGN(wr_size, sizeof (struct ib_sge)) +
2495 num_sge * sizeof (struct ib_sge), GFP_KERNEL);
2496};
2497
Roland Dreier67cdb402005-10-14 15:26:04 -07002498ssize_t ib_uverbs_post_send(struct ib_uverbs_file *file,
Yishai Hadas057aec02015-08-13 18:32:04 +03002499 struct ib_device *ib_dev,
Roland Dreiera74cd4a2006-02-13 16:30:49 -08002500 const char __user *buf, int in_len,
2501 int out_len)
Roland Dreier67cdb402005-10-14 15:26:04 -07002502{
2503 struct ib_uverbs_post_send cmd;
2504 struct ib_uverbs_post_send_resp resp;
2505 struct ib_uverbs_send_wr *user_wr;
2506 struct ib_send_wr *wr = NULL, *last, *next, *bad_wr;
2507 struct ib_qp *qp;
2508 int i, sg_ind;
Roland Dreier9ead1902006-06-17 20:44:49 -07002509 int is_ud;
Roland Dreier67cdb402005-10-14 15:26:04 -07002510 ssize_t ret = -EINVAL;
Mike Marciniszyn1d784b82015-12-01 10:13:51 -05002511 size_t next_size;
Roland Dreier67cdb402005-10-14 15:26:04 -07002512
2513 if (copy_from_user(&cmd, buf, sizeof cmd))
2514 return -EFAULT;
2515
2516 if (in_len < sizeof cmd + cmd.wqe_size * cmd.wr_count +
2517 cmd.sge_count * sizeof (struct ib_uverbs_sge))
2518 return -EINVAL;
2519
2520 if (cmd.wqe_size < sizeof (struct ib_uverbs_send_wr))
2521 return -EINVAL;
2522
2523 user_wr = kmalloc(cmd.wqe_size, GFP_KERNEL);
2524 if (!user_wr)
2525 return -ENOMEM;
2526
Roland Dreier9ead1902006-06-17 20:44:49 -07002527 qp = idr_read_qp(cmd.qp_handle, file->ucontext);
2528 if (!qp)
Roland Dreier67cdb402005-10-14 15:26:04 -07002529 goto out;
2530
Roland Dreier9ead1902006-06-17 20:44:49 -07002531 is_ud = qp->qp_type == IB_QPT_UD;
Roland Dreier67cdb402005-10-14 15:26:04 -07002532 sg_ind = 0;
2533 last = NULL;
2534 for (i = 0; i < cmd.wr_count; ++i) {
2535 if (copy_from_user(user_wr,
2536 buf + sizeof cmd + i * cmd.wqe_size,
2537 cmd.wqe_size)) {
2538 ret = -EFAULT;
Roland Dreier9ead1902006-06-17 20:44:49 -07002539 goto out_put;
Roland Dreier67cdb402005-10-14 15:26:04 -07002540 }
2541
2542 if (user_wr->num_sge + sg_ind > cmd.sge_count) {
2543 ret = -EINVAL;
Roland Dreier9ead1902006-06-17 20:44:49 -07002544 goto out_put;
Roland Dreier67cdb402005-10-14 15:26:04 -07002545 }
2546
Christoph Hellwige622f2f2015-10-08 09:16:33 +01002547 if (is_ud) {
2548 struct ib_ud_wr *ud;
2549
2550 if (user_wr->opcode != IB_WR_SEND &&
2551 user_wr->opcode != IB_WR_SEND_WITH_IMM) {
2552 ret = -EINVAL;
2553 goto out_put;
2554 }
2555
Mike Marciniszyn1d784b82015-12-01 10:13:51 -05002556 next_size = sizeof(*ud);
2557 ud = alloc_wr(next_size, user_wr->num_sge);
Christoph Hellwige622f2f2015-10-08 09:16:33 +01002558 if (!ud) {
2559 ret = -ENOMEM;
2560 goto out_put;
2561 }
2562
2563 ud->ah = idr_read_ah(user_wr->wr.ud.ah, file->ucontext);
2564 if (!ud->ah) {
2565 kfree(ud);
2566 ret = -EINVAL;
2567 goto out_put;
2568 }
2569 ud->remote_qpn = user_wr->wr.ud.remote_qpn;
2570 ud->remote_qkey = user_wr->wr.ud.remote_qkey;
2571
2572 next = &ud->wr;
2573 } else if (user_wr->opcode == IB_WR_RDMA_WRITE_WITH_IMM ||
2574 user_wr->opcode == IB_WR_RDMA_WRITE ||
2575 user_wr->opcode == IB_WR_RDMA_READ) {
2576 struct ib_rdma_wr *rdma;
2577
Mike Marciniszyn1d784b82015-12-01 10:13:51 -05002578 next_size = sizeof(*rdma);
2579 rdma = alloc_wr(next_size, user_wr->num_sge);
Christoph Hellwige622f2f2015-10-08 09:16:33 +01002580 if (!rdma) {
2581 ret = -ENOMEM;
2582 goto out_put;
2583 }
2584
2585 rdma->remote_addr = user_wr->wr.rdma.remote_addr;
2586 rdma->rkey = user_wr->wr.rdma.rkey;
2587
2588 next = &rdma->wr;
2589 } else if (user_wr->opcode == IB_WR_ATOMIC_CMP_AND_SWP ||
2590 user_wr->opcode == IB_WR_ATOMIC_FETCH_AND_ADD) {
2591 struct ib_atomic_wr *atomic;
2592
Mike Marciniszyn1d784b82015-12-01 10:13:51 -05002593 next_size = sizeof(*atomic);
2594 atomic = alloc_wr(next_size, user_wr->num_sge);
Christoph Hellwige622f2f2015-10-08 09:16:33 +01002595 if (!atomic) {
2596 ret = -ENOMEM;
2597 goto out_put;
2598 }
2599
2600 atomic->remote_addr = user_wr->wr.atomic.remote_addr;
2601 atomic->compare_add = user_wr->wr.atomic.compare_add;
2602 atomic->swap = user_wr->wr.atomic.swap;
2603 atomic->rkey = user_wr->wr.atomic.rkey;
2604
2605 next = &atomic->wr;
2606 } else if (user_wr->opcode == IB_WR_SEND ||
2607 user_wr->opcode == IB_WR_SEND_WITH_IMM ||
2608 user_wr->opcode == IB_WR_SEND_WITH_INV) {
Mike Marciniszyn1d784b82015-12-01 10:13:51 -05002609 next_size = sizeof(*next);
2610 next = alloc_wr(next_size, user_wr->num_sge);
Christoph Hellwige622f2f2015-10-08 09:16:33 +01002611 if (!next) {
2612 ret = -ENOMEM;
2613 goto out_put;
2614 }
2615 } else {
2616 ret = -EINVAL;
Roland Dreier9ead1902006-06-17 20:44:49 -07002617 goto out_put;
Roland Dreier67cdb402005-10-14 15:26:04 -07002618 }
2619
Christoph Hellwige622f2f2015-10-08 09:16:33 +01002620 if (user_wr->opcode == IB_WR_SEND_WITH_IMM ||
2621 user_wr->opcode == IB_WR_RDMA_WRITE_WITH_IMM) {
2622 next->ex.imm_data =
2623 (__be32 __force) user_wr->ex.imm_data;
2624 } else if (user_wr->opcode == IB_WR_SEND_WITH_INV) {
2625 next->ex.invalidate_rkey = user_wr->ex.invalidate_rkey;
2626 }
2627
Roland Dreier67cdb402005-10-14 15:26:04 -07002628 if (!last)
2629 wr = next;
2630 else
2631 last->next = next;
2632 last = next;
2633
2634 next->next = NULL;
2635 next->wr_id = user_wr->wr_id;
2636 next->num_sge = user_wr->num_sge;
2637 next->opcode = user_wr->opcode;
2638 next->send_flags = user_wr->send_flags;
Roland Dreier67cdb402005-10-14 15:26:04 -07002639
Roland Dreier67cdb402005-10-14 15:26:04 -07002640 if (next->num_sge) {
2641 next->sg_list = (void *) next +
Mike Marciniszyn1d784b82015-12-01 10:13:51 -05002642 ALIGN(next_size, sizeof(struct ib_sge));
Roland Dreier67cdb402005-10-14 15:26:04 -07002643 if (copy_from_user(next->sg_list,
2644 buf + sizeof cmd +
2645 cmd.wr_count * cmd.wqe_size +
2646 sg_ind * sizeof (struct ib_sge),
2647 next->num_sge * sizeof (struct ib_sge))) {
2648 ret = -EFAULT;
Roland Dreier9ead1902006-06-17 20:44:49 -07002649 goto out_put;
Roland Dreier67cdb402005-10-14 15:26:04 -07002650 }
2651 sg_ind += next->num_sge;
2652 } else
2653 next->sg_list = NULL;
2654 }
2655
2656 resp.bad_wr = 0;
Sean Hefty0e0ec7e2011-08-08 15:31:51 -07002657 ret = qp->device->post_send(qp->real_qp, wr, &bad_wr);
Roland Dreier67cdb402005-10-14 15:26:04 -07002658 if (ret)
2659 for (next = wr; next; next = next->next) {
2660 ++resp.bad_wr;
2661 if (next == bad_wr)
2662 break;
2663 }
2664
2665 if (copy_to_user((void __user *) (unsigned long) cmd.response,
2666 &resp, sizeof resp))
2667 ret = -EFAULT;
2668
Roland Dreier9ead1902006-06-17 20:44:49 -07002669out_put:
2670 put_qp_read(qp);
Roland Dreier67cdb402005-10-14 15:26:04 -07002671
2672 while (wr) {
Christoph Hellwige622f2f2015-10-08 09:16:33 +01002673 if (is_ud && ud_wr(wr)->ah)
2674 put_ah_read(ud_wr(wr)->ah);
Roland Dreier67cdb402005-10-14 15:26:04 -07002675 next = wr->next;
2676 kfree(wr);
2677 wr = next;
2678 }
2679
Krishna Kumar18320822006-06-22 07:47:27 -07002680out:
Roland Dreier67cdb402005-10-14 15:26:04 -07002681 kfree(user_wr);
2682
2683 return ret ? ret : in_len;
2684}
2685
2686static struct ib_recv_wr *ib_uverbs_unmarshall_recv(const char __user *buf,
2687 int in_len,
2688 u32 wr_count,
2689 u32 sge_count,
2690 u32 wqe_size)
2691{
2692 struct ib_uverbs_recv_wr *user_wr;
2693 struct ib_recv_wr *wr = NULL, *last, *next;
2694 int sg_ind;
2695 int i;
2696 int ret;
2697
2698 if (in_len < wqe_size * wr_count +
2699 sge_count * sizeof (struct ib_uverbs_sge))
2700 return ERR_PTR(-EINVAL);
2701
2702 if (wqe_size < sizeof (struct ib_uverbs_recv_wr))
2703 return ERR_PTR(-EINVAL);
2704
2705 user_wr = kmalloc(wqe_size, GFP_KERNEL);
2706 if (!user_wr)
2707 return ERR_PTR(-ENOMEM);
2708
2709 sg_ind = 0;
2710 last = NULL;
2711 for (i = 0; i < wr_count; ++i) {
2712 if (copy_from_user(user_wr, buf + i * wqe_size,
2713 wqe_size)) {
2714 ret = -EFAULT;
2715 goto err;
2716 }
2717
2718 if (user_wr->num_sge + sg_ind > sge_count) {
2719 ret = -EINVAL;
2720 goto err;
2721 }
2722
2723 next = kmalloc(ALIGN(sizeof *next, sizeof (struct ib_sge)) +
2724 user_wr->num_sge * sizeof (struct ib_sge),
2725 GFP_KERNEL);
2726 if (!next) {
2727 ret = -ENOMEM;
2728 goto err;
2729 }
2730
2731 if (!last)
2732 wr = next;
2733 else
2734 last->next = next;
2735 last = next;
2736
2737 next->next = NULL;
2738 next->wr_id = user_wr->wr_id;
2739 next->num_sge = user_wr->num_sge;
2740
2741 if (next->num_sge) {
2742 next->sg_list = (void *) next +
2743 ALIGN(sizeof *next, sizeof (struct ib_sge));
2744 if (copy_from_user(next->sg_list,
2745 buf + wr_count * wqe_size +
2746 sg_ind * sizeof (struct ib_sge),
2747 next->num_sge * sizeof (struct ib_sge))) {
2748 ret = -EFAULT;
2749 goto err;
2750 }
2751 sg_ind += next->num_sge;
2752 } else
2753 next->sg_list = NULL;
2754 }
2755
2756 kfree(user_wr);
2757 return wr;
2758
2759err:
2760 kfree(user_wr);
2761
2762 while (wr) {
2763 next = wr->next;
2764 kfree(wr);
2765 wr = next;
2766 }
2767
2768 return ERR_PTR(ret);
2769}
2770
2771ssize_t ib_uverbs_post_recv(struct ib_uverbs_file *file,
Yishai Hadas057aec02015-08-13 18:32:04 +03002772 struct ib_device *ib_dev,
Roland Dreiera74cd4a2006-02-13 16:30:49 -08002773 const char __user *buf, int in_len,
2774 int out_len)
Roland Dreier67cdb402005-10-14 15:26:04 -07002775{
2776 struct ib_uverbs_post_recv cmd;
2777 struct ib_uverbs_post_recv_resp resp;
2778 struct ib_recv_wr *wr, *next, *bad_wr;
2779 struct ib_qp *qp;
2780 ssize_t ret = -EINVAL;
2781
2782 if (copy_from_user(&cmd, buf, sizeof cmd))
2783 return -EFAULT;
2784
2785 wr = ib_uverbs_unmarshall_recv(buf + sizeof cmd,
2786 in_len - sizeof cmd, cmd.wr_count,
2787 cmd.sge_count, cmd.wqe_size);
2788 if (IS_ERR(wr))
2789 return PTR_ERR(wr);
2790
Roland Dreier9ead1902006-06-17 20:44:49 -07002791 qp = idr_read_qp(cmd.qp_handle, file->ucontext);
2792 if (!qp)
Roland Dreier67cdb402005-10-14 15:26:04 -07002793 goto out;
2794
2795 resp.bad_wr = 0;
Sean Hefty0e0ec7e2011-08-08 15:31:51 -07002796 ret = qp->device->post_recv(qp->real_qp, wr, &bad_wr);
Roland Dreier9ead1902006-06-17 20:44:49 -07002797
2798 put_qp_read(qp);
2799
Roland Dreier67cdb402005-10-14 15:26:04 -07002800 if (ret)
2801 for (next = wr; next; next = next->next) {
2802 ++resp.bad_wr;
2803 if (next == bad_wr)
2804 break;
2805 }
2806
Roland Dreier67cdb402005-10-14 15:26:04 -07002807 if (copy_to_user((void __user *) (unsigned long) cmd.response,
2808 &resp, sizeof resp))
2809 ret = -EFAULT;
2810
2811out:
Roland Dreier67cdb402005-10-14 15:26:04 -07002812 while (wr) {
2813 next = wr->next;
2814 kfree(wr);
2815 wr = next;
2816 }
2817
2818 return ret ? ret : in_len;
2819}
2820
2821ssize_t ib_uverbs_post_srq_recv(struct ib_uverbs_file *file,
Yishai Hadas057aec02015-08-13 18:32:04 +03002822 struct ib_device *ib_dev,
Roland Dreiera74cd4a2006-02-13 16:30:49 -08002823 const char __user *buf, int in_len,
2824 int out_len)
Roland Dreier67cdb402005-10-14 15:26:04 -07002825{
2826 struct ib_uverbs_post_srq_recv cmd;
2827 struct ib_uverbs_post_srq_recv_resp resp;
2828 struct ib_recv_wr *wr, *next, *bad_wr;
2829 struct ib_srq *srq;
2830 ssize_t ret = -EINVAL;
2831
2832 if (copy_from_user(&cmd, buf, sizeof cmd))
2833 return -EFAULT;
2834
2835 wr = ib_uverbs_unmarshall_recv(buf + sizeof cmd,
2836 in_len - sizeof cmd, cmd.wr_count,
2837 cmd.sge_count, cmd.wqe_size);
2838 if (IS_ERR(wr))
2839 return PTR_ERR(wr);
2840
Roland Dreier9ead1902006-06-17 20:44:49 -07002841 srq = idr_read_srq(cmd.srq_handle, file->ucontext);
2842 if (!srq)
Roland Dreier67cdb402005-10-14 15:26:04 -07002843 goto out;
2844
2845 resp.bad_wr = 0;
2846 ret = srq->device->post_srq_recv(srq, wr, &bad_wr);
Roland Dreier9ead1902006-06-17 20:44:49 -07002847
2848 put_srq_read(srq);
2849
Roland Dreier67cdb402005-10-14 15:26:04 -07002850 if (ret)
2851 for (next = wr; next; next = next->next) {
2852 ++resp.bad_wr;
2853 if (next == bad_wr)
2854 break;
2855 }
2856
Roland Dreier67cdb402005-10-14 15:26:04 -07002857 if (copy_to_user((void __user *) (unsigned long) cmd.response,
2858 &resp, sizeof resp))
2859 ret = -EFAULT;
2860
2861out:
Roland Dreier67cdb402005-10-14 15:26:04 -07002862 while (wr) {
2863 next = wr->next;
2864 kfree(wr);
2865 wr = next;
2866 }
2867
2868 return ret ? ret : in_len;
2869}
2870
2871ssize_t ib_uverbs_create_ah(struct ib_uverbs_file *file,
Yishai Hadas057aec02015-08-13 18:32:04 +03002872 struct ib_device *ib_dev,
Roland Dreier67cdb402005-10-14 15:26:04 -07002873 const char __user *buf, int in_len,
2874 int out_len)
2875{
2876 struct ib_uverbs_create_ah cmd;
2877 struct ib_uverbs_create_ah_resp resp;
2878 struct ib_uobject *uobj;
2879 struct ib_pd *pd;
2880 struct ib_ah *ah;
2881 struct ib_ah_attr attr;
2882 int ret;
2883
2884 if (out_len < sizeof resp)
2885 return -ENOSPC;
2886
2887 if (copy_from_user(&cmd, buf, sizeof cmd))
2888 return -EFAULT;
2889
Boris Pismenny84b00cd2017-06-27 15:09:13 +03002890 if (cmd.attr.port_num < rdma_start_port(ib_dev) ||
2891 cmd.attr.port_num > rdma_end_port(ib_dev))
2892 return -EINVAL;
2893
Roland Dreier67cdb402005-10-14 15:26:04 -07002894 uobj = kmalloc(sizeof *uobj, GFP_KERNEL);
2895 if (!uobj)
2896 return -ENOMEM;
2897
Roland Dreier3bea57a2012-04-30 10:27:26 -07002898 init_uobj(uobj, cmd.user_handle, file->ucontext, &ah_lock_class);
Roland Dreier9ead1902006-06-17 20:44:49 -07002899 down_write(&uobj->mutex);
Roland Dreier67cdb402005-10-14 15:26:04 -07002900
Roland Dreier9ead1902006-06-17 20:44:49 -07002901 pd = idr_read_pd(cmd.pd_handle, file->ucontext);
2902 if (!pd) {
Roland Dreier67cdb402005-10-14 15:26:04 -07002903 ret = -EINVAL;
Roland Dreier9ead1902006-06-17 20:44:49 -07002904 goto err;
Roland Dreier67cdb402005-10-14 15:26:04 -07002905 }
2906
Roland Dreier67cdb402005-10-14 15:26:04 -07002907 attr.dlid = cmd.attr.dlid;
2908 attr.sl = cmd.attr.sl;
2909 attr.src_path_bits = cmd.attr.src_path_bits;
2910 attr.static_rate = cmd.attr.static_rate;
Ralph Campbellea5d4a62006-01-06 16:24:45 -08002911 attr.ah_flags = cmd.attr.is_global ? IB_AH_GRH : 0;
Roland Dreier67cdb402005-10-14 15:26:04 -07002912 attr.port_num = cmd.attr.port_num;
2913 attr.grh.flow_label = cmd.attr.grh.flow_label;
2914 attr.grh.sgid_index = cmd.attr.grh.sgid_index;
2915 attr.grh.hop_limit = cmd.attr.grh.hop_limit;
2916 attr.grh.traffic_class = cmd.attr.grh.traffic_class;
Devesh Sharma8b0f93d2014-09-26 20:45:32 +05302917 memset(&attr.dmac, 0, sizeof(attr.dmac));
Roland Dreier67cdb402005-10-14 15:26:04 -07002918 memcpy(attr.grh.dgid.raw, cmd.attr.grh.dgid, 16);
2919
2920 ah = ib_create_ah(pd, &attr);
2921 if (IS_ERR(ah)) {
2922 ret = PTR_ERR(ah);
Michael S. Tsirkinec924b42006-07-17 18:20:51 +03002923 goto err_put;
Roland Dreier67cdb402005-10-14 15:26:04 -07002924 }
2925
Roland Dreier9ead1902006-06-17 20:44:49 -07002926 ah->uobject = uobj;
2927 uobj->object = ah;
Roland Dreier67cdb402005-10-14 15:26:04 -07002928
Roland Dreier9ead1902006-06-17 20:44:49 -07002929 ret = idr_add_uobj(&ib_uverbs_ah_idr, uobj);
Roland Dreier67cdb402005-10-14 15:26:04 -07002930 if (ret)
2931 goto err_destroy;
2932
2933 resp.ah_handle = uobj->id;
2934
2935 if (copy_to_user((void __user *) (unsigned long) cmd.response,
2936 &resp, sizeof resp)) {
2937 ret = -EFAULT;
Roland Dreier9ead1902006-06-17 20:44:49 -07002938 goto err_copy;
Roland Dreier67cdb402005-10-14 15:26:04 -07002939 }
2940
Roland Dreier9ead1902006-06-17 20:44:49 -07002941 put_pd_read(pd);
2942
Ingo Molnar95ed6442006-01-13 14:51:39 -08002943 mutex_lock(&file->mutex);
Roland Dreier67cdb402005-10-14 15:26:04 -07002944 list_add_tail(&uobj->list, &file->ucontext->ah_list);
Ingo Molnar95ed6442006-01-13 14:51:39 -08002945 mutex_unlock(&file->mutex);
Roland Dreier67cdb402005-10-14 15:26:04 -07002946
Roland Dreier9ead1902006-06-17 20:44:49 -07002947 uobj->live = 1;
2948
2949 up_write(&uobj->mutex);
Roland Dreier67cdb402005-10-14 15:26:04 -07002950
2951 return in_len;
2952
Roland Dreier9ead1902006-06-17 20:44:49 -07002953err_copy:
2954 idr_remove_uobj(&ib_uverbs_ah_idr, uobj);
Roland Dreier67cdb402005-10-14 15:26:04 -07002955
2956err_destroy:
2957 ib_destroy_ah(ah);
2958
Michael S. Tsirkinec924b42006-07-17 18:20:51 +03002959err_put:
2960 put_pd_read(pd);
2961
Roland Dreier9ead1902006-06-17 20:44:49 -07002962err:
2963 put_uobj_write(uobj);
Roland Dreier67cdb402005-10-14 15:26:04 -07002964 return ret;
2965}
2966
2967ssize_t ib_uverbs_destroy_ah(struct ib_uverbs_file *file,
Yishai Hadas057aec02015-08-13 18:32:04 +03002968 struct ib_device *ib_dev,
Roland Dreier67cdb402005-10-14 15:26:04 -07002969 const char __user *buf, int in_len, int out_len)
2970{
2971 struct ib_uverbs_destroy_ah cmd;
2972 struct ib_ah *ah;
2973 struct ib_uobject *uobj;
Roland Dreier9ead1902006-06-17 20:44:49 -07002974 int ret;
Roland Dreier67cdb402005-10-14 15:26:04 -07002975
2976 if (copy_from_user(&cmd, buf, sizeof cmd))
2977 return -EFAULT;
2978
Roland Dreier9ead1902006-06-17 20:44:49 -07002979 uobj = idr_write_uobj(&ib_uverbs_ah_idr, cmd.ah_handle, file->ucontext);
2980 if (!uobj)
2981 return -EINVAL;
2982 ah = uobj->object;
Roland Dreier67cdb402005-10-14 15:26:04 -07002983
2984 ret = ib_destroy_ah(ah);
Roland Dreier9ead1902006-06-17 20:44:49 -07002985 if (!ret)
2986 uobj->live = 0;
Roland Dreier67cdb402005-10-14 15:26:04 -07002987
Roland Dreier9ead1902006-06-17 20:44:49 -07002988 put_uobj_write(uobj);
2989
2990 if (ret)
2991 return ret;
2992
2993 idr_remove_uobj(&ib_uverbs_ah_idr, uobj);
Roland Dreier67cdb402005-10-14 15:26:04 -07002994
Ingo Molnar95ed6442006-01-13 14:51:39 -08002995 mutex_lock(&file->mutex);
Roland Dreier67cdb402005-10-14 15:26:04 -07002996 list_del(&uobj->list);
Ingo Molnar95ed6442006-01-13 14:51:39 -08002997 mutex_unlock(&file->mutex);
Roland Dreier67cdb402005-10-14 15:26:04 -07002998
Roland Dreier9ead1902006-06-17 20:44:49 -07002999 put_uobj(uobj);
Roland Dreier67cdb402005-10-14 15:26:04 -07003000
Roland Dreier9ead1902006-06-17 20:44:49 -07003001 return in_len;
Roland Dreier67cdb402005-10-14 15:26:04 -07003002}
3003
Roland Dreierbc38a6a2005-07-07 17:57:13 -07003004ssize_t ib_uverbs_attach_mcast(struct ib_uverbs_file *file,
Yishai Hadas057aec02015-08-13 18:32:04 +03003005 struct ib_device *ib_dev,
Roland Dreierbc38a6a2005-07-07 17:57:13 -07003006 const char __user *buf, int in_len,
3007 int out_len)
3008{
3009 struct ib_uverbs_attach_mcast cmd;
3010 struct ib_qp *qp;
Roland Dreier9ead1902006-06-17 20:44:49 -07003011 struct ib_uqp_object *obj;
Jack Morgensteinf4e40152005-11-29 16:57:01 -08003012 struct ib_uverbs_mcast_entry *mcast;
Roland Dreier9ead1902006-06-17 20:44:49 -07003013 int ret;
Roland Dreierbc38a6a2005-07-07 17:57:13 -07003014
3015 if (copy_from_user(&cmd, buf, sizeof cmd))
3016 return -EFAULT;
3017
Eli Cohene214a0f2012-01-03 20:36:48 -08003018 qp = idr_write_qp(cmd.qp_handle, file->ucontext);
Roland Dreier9ead1902006-06-17 20:44:49 -07003019 if (!qp)
3020 return -EINVAL;
Roland Dreierbc38a6a2005-07-07 17:57:13 -07003021
Roland Dreier9ead1902006-06-17 20:44:49 -07003022 obj = container_of(qp->uobject, struct ib_uqp_object, uevent.uobject);
Roland Dreierbc38a6a2005-07-07 17:57:13 -07003023
Roland Dreier9ead1902006-06-17 20:44:49 -07003024 list_for_each_entry(mcast, &obj->mcast_list, list)
Jack Morgensteinf4e40152005-11-29 16:57:01 -08003025 if (cmd.mlid == mcast->lid &&
3026 !memcmp(cmd.gid, mcast->gid.raw, sizeof mcast->gid.raw)) {
3027 ret = 0;
Roland Dreier9ead1902006-06-17 20:44:49 -07003028 goto out_put;
Jack Morgensteinf4e40152005-11-29 16:57:01 -08003029 }
3030
3031 mcast = kmalloc(sizeof *mcast, GFP_KERNEL);
3032 if (!mcast) {
3033 ret = -ENOMEM;
Roland Dreier9ead1902006-06-17 20:44:49 -07003034 goto out_put;
Jack Morgensteinf4e40152005-11-29 16:57:01 -08003035 }
3036
3037 mcast->lid = cmd.mlid;
3038 memcpy(mcast->gid.raw, cmd.gid, sizeof mcast->gid.raw);
3039
3040 ret = ib_attach_mcast(qp, &mcast->gid, cmd.mlid);
Roland Dreier9ead1902006-06-17 20:44:49 -07003041 if (!ret)
3042 list_add_tail(&mcast->list, &obj->mcast_list);
3043 else
Jack Morgensteinf4e40152005-11-29 16:57:01 -08003044 kfree(mcast);
3045
Roland Dreier9ead1902006-06-17 20:44:49 -07003046out_put:
Eli Cohene214a0f2012-01-03 20:36:48 -08003047 put_qp_write(qp);
Roland Dreierbc38a6a2005-07-07 17:57:13 -07003048
3049 return ret ? ret : in_len;
3050}
3051
3052ssize_t ib_uverbs_detach_mcast(struct ib_uverbs_file *file,
Yishai Hadas057aec02015-08-13 18:32:04 +03003053 struct ib_device *ib_dev,
Roland Dreierbc38a6a2005-07-07 17:57:13 -07003054 const char __user *buf, int in_len,
3055 int out_len)
3056{
3057 struct ib_uverbs_detach_mcast cmd;
Roland Dreier9ead1902006-06-17 20:44:49 -07003058 struct ib_uqp_object *obj;
Roland Dreierbc38a6a2005-07-07 17:57:13 -07003059 struct ib_qp *qp;
Jack Morgensteinf4e40152005-11-29 16:57:01 -08003060 struct ib_uverbs_mcast_entry *mcast;
Roland Dreierbc38a6a2005-07-07 17:57:13 -07003061 int ret = -EINVAL;
3062
3063 if (copy_from_user(&cmd, buf, sizeof cmd))
3064 return -EFAULT;
3065
Eli Cohene214a0f2012-01-03 20:36:48 -08003066 qp = idr_write_qp(cmd.qp_handle, file->ucontext);
Roland Dreier9ead1902006-06-17 20:44:49 -07003067 if (!qp)
3068 return -EINVAL;
Roland Dreierbc38a6a2005-07-07 17:57:13 -07003069
Jack Morgensteinf4e40152005-11-29 16:57:01 -08003070 ret = ib_detach_mcast(qp, (union ib_gid *) cmd.gid, cmd.mlid);
3071 if (ret)
Roland Dreier9ead1902006-06-17 20:44:49 -07003072 goto out_put;
Jack Morgensteinf4e40152005-11-29 16:57:01 -08003073
Roland Dreier9ead1902006-06-17 20:44:49 -07003074 obj = container_of(qp->uobject, struct ib_uqp_object, uevent.uobject);
Jack Morgensteinf4e40152005-11-29 16:57:01 -08003075
Roland Dreier9ead1902006-06-17 20:44:49 -07003076 list_for_each_entry(mcast, &obj->mcast_list, list)
Jack Morgensteinf4e40152005-11-29 16:57:01 -08003077 if (cmd.mlid == mcast->lid &&
3078 !memcmp(cmd.gid, mcast->gid.raw, sizeof mcast->gid.raw)) {
3079 list_del(&mcast->list);
3080 kfree(mcast);
3081 break;
3082 }
3083
Roland Dreier9ead1902006-06-17 20:44:49 -07003084out_put:
Eli Cohene214a0f2012-01-03 20:36:48 -08003085 put_qp_write(qp);
Roland Dreierbc38a6a2005-07-07 17:57:13 -07003086
3087 return ret ? ret : in_len;
3088}
Roland Dreierf520ba52005-08-18 12:24:13 -07003089
Maor Gottlieb15dfbd62016-08-30 16:58:32 +03003090static size_t kern_spec_filter_sz(struct ib_uverbs_flow_spec_hdr *spec)
3091{
3092 /* Returns user space filter size, includes padding */
3093 return (spec->size - sizeof(struct ib_uverbs_flow_spec_hdr)) / 2;
3094}
3095
3096static ssize_t spec_filter_size(void *kern_spec_filter, u16 kern_filter_size,
3097 u16 ib_real_filter_sz)
3098{
3099 /*
3100 * User space filter structures must be 64 bit aligned, otherwise this
3101 * may pass, but we won't handle additional new attributes.
3102 */
3103
3104 if (kern_filter_size > ib_real_filter_sz) {
3105 if (memchr_inv(kern_spec_filter +
3106 ib_real_filter_sz, 0,
3107 kern_filter_size - ib_real_filter_sz))
3108 return -EINVAL;
3109 return ib_real_filter_sz;
3110 }
3111 return kern_filter_size;
3112}
3113
Yann Droneaudb68c9562013-11-06 23:21:46 +01003114static int kern_spec_to_ib_spec(struct ib_uverbs_flow_spec *kern_spec,
Hadar Hen Zion436f2ad2013-08-14 13:58:30 +03003115 union ib_flow_spec *ib_spec)
3116{
Maor Gottlieb15dfbd62016-08-30 16:58:32 +03003117 ssize_t actual_filter_sz;
3118 ssize_t kern_filter_sz;
3119 ssize_t ib_filter_sz;
3120 void *kern_spec_mask;
3121 void *kern_spec_val;
3122
Yann Droneaudc780d822013-12-11 23:01:49 +01003123 if (kern_spec->reserved)
3124 return -EINVAL;
3125
Hadar Hen Zion436f2ad2013-08-14 13:58:30 +03003126 ib_spec->type = kern_spec->type;
3127
Maor Gottlieb15dfbd62016-08-30 16:58:32 +03003128 kern_filter_sz = kern_spec_filter_sz(&kern_spec->hdr);
3129 /* User flow spec size must be aligned to 4 bytes */
3130 if (kern_filter_sz != ALIGN(kern_filter_sz, 4))
3131 return -EINVAL;
3132
3133 kern_spec_val = (void *)kern_spec +
3134 sizeof(struct ib_uverbs_flow_spec_hdr);
3135 kern_spec_mask = kern_spec_val + kern_filter_sz;
3136
Hadar Hen Zion436f2ad2013-08-14 13:58:30 +03003137 switch (ib_spec->type) {
3138 case IB_FLOW_SPEC_ETH:
Maor Gottlieb15dfbd62016-08-30 16:58:32 +03003139 ib_filter_sz = offsetof(struct ib_flow_eth_filter, real_sz);
3140 actual_filter_sz = spec_filter_size(kern_spec_mask,
3141 kern_filter_sz,
3142 ib_filter_sz);
3143 if (actual_filter_sz <= 0)
Hadar Hen Zion436f2ad2013-08-14 13:58:30 +03003144 return -EINVAL;
Maor Gottlieb15dfbd62016-08-30 16:58:32 +03003145 ib_spec->size = sizeof(struct ib_flow_spec_eth);
3146 memcpy(&ib_spec->eth.val, kern_spec_val, actual_filter_sz);
3147 memcpy(&ib_spec->eth.mask, kern_spec_mask, actual_filter_sz);
Hadar Hen Zion436f2ad2013-08-14 13:58:30 +03003148 break;
3149 case IB_FLOW_SPEC_IPV4:
Maor Gottlieb15dfbd62016-08-30 16:58:32 +03003150 ib_filter_sz = offsetof(struct ib_flow_ipv4_filter, real_sz);
3151 actual_filter_sz = spec_filter_size(kern_spec_mask,
3152 kern_filter_sz,
3153 ib_filter_sz);
3154 if (actual_filter_sz <= 0)
Hadar Hen Zion436f2ad2013-08-14 13:58:30 +03003155 return -EINVAL;
Maor Gottlieb15dfbd62016-08-30 16:58:32 +03003156 ib_spec->size = sizeof(struct ib_flow_spec_ipv4);
3157 memcpy(&ib_spec->ipv4.val, kern_spec_val, actual_filter_sz);
3158 memcpy(&ib_spec->ipv4.mask, kern_spec_mask, actual_filter_sz);
Hadar Hen Zion436f2ad2013-08-14 13:58:30 +03003159 break;
Maor Gottlieb4c2aae72016-06-17 15:14:50 +03003160 case IB_FLOW_SPEC_IPV6:
Maor Gottlieb15dfbd62016-08-30 16:58:32 +03003161 ib_filter_sz = offsetof(struct ib_flow_ipv6_filter, real_sz);
3162 actual_filter_sz = spec_filter_size(kern_spec_mask,
3163 kern_filter_sz,
3164 ib_filter_sz);
3165 if (actual_filter_sz <= 0)
Maor Gottlieb4c2aae72016-06-17 15:14:50 +03003166 return -EINVAL;
Maor Gottlieb15dfbd62016-08-30 16:58:32 +03003167 ib_spec->size = sizeof(struct ib_flow_spec_ipv6);
3168 memcpy(&ib_spec->ipv6.val, kern_spec_val, actual_filter_sz);
3169 memcpy(&ib_spec->ipv6.mask, kern_spec_mask, actual_filter_sz);
Maor Gottlieba72c6a22016-08-30 16:58:34 +03003170
3171 if ((ntohl(ib_spec->ipv6.mask.flow_label)) >= BIT(20) ||
3172 (ntohl(ib_spec->ipv6.val.flow_label)) >= BIT(20))
3173 return -EINVAL;
Maor Gottlieb4c2aae72016-06-17 15:14:50 +03003174 break;
Hadar Hen Zion436f2ad2013-08-14 13:58:30 +03003175 case IB_FLOW_SPEC_TCP:
3176 case IB_FLOW_SPEC_UDP:
Maor Gottlieb15dfbd62016-08-30 16:58:32 +03003177 ib_filter_sz = offsetof(struct ib_flow_tcp_udp_filter, real_sz);
3178 actual_filter_sz = spec_filter_size(kern_spec_mask,
3179 kern_filter_sz,
3180 ib_filter_sz);
3181 if (actual_filter_sz <= 0)
Hadar Hen Zion436f2ad2013-08-14 13:58:30 +03003182 return -EINVAL;
Maor Gottlieb15dfbd62016-08-30 16:58:32 +03003183 ib_spec->size = sizeof(struct ib_flow_spec_tcp_udp);
3184 memcpy(&ib_spec->tcp_udp.val, kern_spec_val, actual_filter_sz);
3185 memcpy(&ib_spec->tcp_udp.mask, kern_spec_mask, actual_filter_sz);
Hadar Hen Zion436f2ad2013-08-14 13:58:30 +03003186 break;
3187 default:
3188 return -EINVAL;
3189 }
3190 return 0;
3191}
3192
Yishai Hadasf213c052016-05-23 15:20:49 +03003193int ib_uverbs_ex_create_wq(struct ib_uverbs_file *file,
3194 struct ib_device *ib_dev,
3195 struct ib_udata *ucore,
3196 struct ib_udata *uhw)
3197{
3198 struct ib_uverbs_ex_create_wq cmd = {};
3199 struct ib_uverbs_ex_create_wq_resp resp = {};
3200 struct ib_uwq_object *obj;
3201 int err = 0;
3202 struct ib_cq *cq;
3203 struct ib_pd *pd;
3204 struct ib_wq *wq;
3205 struct ib_wq_init_attr wq_init_attr = {};
3206 size_t required_cmd_sz;
3207 size_t required_resp_len;
3208
3209 required_cmd_sz = offsetof(typeof(cmd), max_sge) + sizeof(cmd.max_sge);
3210 required_resp_len = offsetof(typeof(resp), wqn) + sizeof(resp.wqn);
3211
3212 if (ucore->inlen < required_cmd_sz)
3213 return -EINVAL;
3214
3215 if (ucore->outlen < required_resp_len)
3216 return -ENOSPC;
3217
3218 if (ucore->inlen > sizeof(cmd) &&
3219 !ib_is_udata_cleared(ucore, sizeof(cmd),
3220 ucore->inlen - sizeof(cmd)))
3221 return -EOPNOTSUPP;
3222
3223 err = ib_copy_from_udata(&cmd, ucore, min(sizeof(cmd), ucore->inlen));
3224 if (err)
3225 return err;
3226
3227 if (cmd.comp_mask)
3228 return -EOPNOTSUPP;
3229
3230 obj = kmalloc(sizeof(*obj), GFP_KERNEL);
3231 if (!obj)
3232 return -ENOMEM;
3233
3234 init_uobj(&obj->uevent.uobject, cmd.user_handle, file->ucontext,
3235 &wq_lock_class);
3236 down_write(&obj->uevent.uobject.mutex);
3237 pd = idr_read_pd(cmd.pd_handle, file->ucontext);
3238 if (!pd) {
3239 err = -EINVAL;
3240 goto err_uobj;
3241 }
3242
3243 cq = idr_read_cq(cmd.cq_handle, file->ucontext, 0);
3244 if (!cq) {
3245 err = -EINVAL;
3246 goto err_put_pd;
3247 }
3248
3249 wq_init_attr.cq = cq;
3250 wq_init_attr.max_sge = cmd.max_sge;
3251 wq_init_attr.max_wr = cmd.max_wr;
3252 wq_init_attr.wq_context = file;
3253 wq_init_attr.wq_type = cmd.wq_type;
3254 wq_init_attr.event_handler = ib_uverbs_wq_event_handler;
3255 obj->uevent.events_reported = 0;
3256 INIT_LIST_HEAD(&obj->uevent.event_list);
3257 wq = pd->device->create_wq(pd, &wq_init_attr, uhw);
3258 if (IS_ERR(wq)) {
3259 err = PTR_ERR(wq);
3260 goto err_put_cq;
3261 }
3262
3263 wq->uobject = &obj->uevent.uobject;
3264 obj->uevent.uobject.object = wq;
3265 wq->wq_type = wq_init_attr.wq_type;
3266 wq->cq = cq;
3267 wq->pd = pd;
3268 wq->device = pd->device;
3269 wq->wq_context = wq_init_attr.wq_context;
3270 atomic_set(&wq->usecnt, 0);
3271 atomic_inc(&pd->usecnt);
3272 atomic_inc(&cq->usecnt);
3273 wq->uobject = &obj->uevent.uobject;
3274 obj->uevent.uobject.object = wq;
3275 err = idr_add_uobj(&ib_uverbs_wq_idr, &obj->uevent.uobject);
3276 if (err)
3277 goto destroy_wq;
3278
3279 memset(&resp, 0, sizeof(resp));
3280 resp.wq_handle = obj->uevent.uobject.id;
3281 resp.max_sge = wq_init_attr.max_sge;
3282 resp.max_wr = wq_init_attr.max_wr;
3283 resp.wqn = wq->wq_num;
3284 resp.response_length = required_resp_len;
3285 err = ib_copy_to_udata(ucore,
3286 &resp, resp.response_length);
3287 if (err)
3288 goto err_copy;
3289
3290 put_pd_read(pd);
3291 put_cq_read(cq);
3292
3293 mutex_lock(&file->mutex);
3294 list_add_tail(&obj->uevent.uobject.list, &file->ucontext->wq_list);
3295 mutex_unlock(&file->mutex);
3296
3297 obj->uevent.uobject.live = 1;
3298 up_write(&obj->uevent.uobject.mutex);
3299 return 0;
3300
3301err_copy:
3302 idr_remove_uobj(&ib_uverbs_wq_idr, &obj->uevent.uobject);
3303destroy_wq:
3304 ib_destroy_wq(wq);
3305err_put_cq:
3306 put_cq_read(cq);
3307err_put_pd:
3308 put_pd_read(pd);
3309err_uobj:
3310 put_uobj_write(&obj->uevent.uobject);
3311
3312 return err;
3313}
3314
3315int ib_uverbs_ex_destroy_wq(struct ib_uverbs_file *file,
3316 struct ib_device *ib_dev,
3317 struct ib_udata *ucore,
3318 struct ib_udata *uhw)
3319{
3320 struct ib_uverbs_ex_destroy_wq cmd = {};
3321 struct ib_uverbs_ex_destroy_wq_resp resp = {};
3322 struct ib_wq *wq;
3323 struct ib_uobject *uobj;
3324 struct ib_uwq_object *obj;
3325 size_t required_cmd_sz;
3326 size_t required_resp_len;
3327 int ret;
3328
3329 required_cmd_sz = offsetof(typeof(cmd), wq_handle) + sizeof(cmd.wq_handle);
3330 required_resp_len = offsetof(typeof(resp), reserved) + sizeof(resp.reserved);
3331
3332 if (ucore->inlen < required_cmd_sz)
3333 return -EINVAL;
3334
3335 if (ucore->outlen < required_resp_len)
3336 return -ENOSPC;
3337
3338 if (ucore->inlen > sizeof(cmd) &&
3339 !ib_is_udata_cleared(ucore, sizeof(cmd),
3340 ucore->inlen - sizeof(cmd)))
3341 return -EOPNOTSUPP;
3342
3343 ret = ib_copy_from_udata(&cmd, ucore, min(sizeof(cmd), ucore->inlen));
3344 if (ret)
3345 return ret;
3346
3347 if (cmd.comp_mask)
3348 return -EOPNOTSUPP;
3349
3350 resp.response_length = required_resp_len;
3351 uobj = idr_write_uobj(&ib_uverbs_wq_idr, cmd.wq_handle,
3352 file->ucontext);
3353 if (!uobj)
3354 return -EINVAL;
3355
3356 wq = uobj->object;
3357 obj = container_of(uobj, struct ib_uwq_object, uevent.uobject);
3358 ret = ib_destroy_wq(wq);
3359 if (!ret)
3360 uobj->live = 0;
3361
3362 put_uobj_write(uobj);
3363 if (ret)
3364 return ret;
3365
3366 idr_remove_uobj(&ib_uverbs_wq_idr, uobj);
3367
3368 mutex_lock(&file->mutex);
3369 list_del(&uobj->list);
3370 mutex_unlock(&file->mutex);
3371
3372 ib_uverbs_release_uevent(file, &obj->uevent);
3373 resp.events_reported = obj->uevent.events_reported;
3374 put_uobj(uobj);
3375
3376 ret = ib_copy_to_udata(ucore, &resp, resp.response_length);
3377 if (ret)
3378 return ret;
3379
3380 return 0;
3381}
3382
3383int ib_uverbs_ex_modify_wq(struct ib_uverbs_file *file,
3384 struct ib_device *ib_dev,
3385 struct ib_udata *ucore,
3386 struct ib_udata *uhw)
3387{
3388 struct ib_uverbs_ex_modify_wq cmd = {};
3389 struct ib_wq *wq;
3390 struct ib_wq_attr wq_attr = {};
3391 size_t required_cmd_sz;
3392 int ret;
3393
3394 required_cmd_sz = offsetof(typeof(cmd), curr_wq_state) + sizeof(cmd.curr_wq_state);
3395 if (ucore->inlen < required_cmd_sz)
3396 return -EINVAL;
3397
3398 if (ucore->inlen > sizeof(cmd) &&
3399 !ib_is_udata_cleared(ucore, sizeof(cmd),
3400 ucore->inlen - sizeof(cmd)))
3401 return -EOPNOTSUPP;
3402
3403 ret = ib_copy_from_udata(&cmd, ucore, min(sizeof(cmd), ucore->inlen));
3404 if (ret)
3405 return ret;
3406
3407 if (!cmd.attr_mask)
3408 return -EINVAL;
3409
3410 if (cmd.attr_mask > (IB_WQ_STATE | IB_WQ_CUR_STATE))
3411 return -EINVAL;
3412
3413 wq = idr_read_wq(cmd.wq_handle, file->ucontext);
3414 if (!wq)
3415 return -EINVAL;
3416
3417 wq_attr.curr_wq_state = cmd.curr_wq_state;
3418 wq_attr.wq_state = cmd.wq_state;
3419 ret = wq->device->modify_wq(wq, &wq_attr, cmd.attr_mask, uhw);
3420 put_wq_read(wq);
3421 return ret;
3422}
3423
Yishai Hadasde019a92016-05-23 15:20:52 +03003424int ib_uverbs_ex_create_rwq_ind_table(struct ib_uverbs_file *file,
3425 struct ib_device *ib_dev,
3426 struct ib_udata *ucore,
3427 struct ib_udata *uhw)
3428{
3429 struct ib_uverbs_ex_create_rwq_ind_table cmd = {};
3430 struct ib_uverbs_ex_create_rwq_ind_table_resp resp = {};
3431 struct ib_uobject *uobj;
3432 int err = 0;
3433 struct ib_rwq_ind_table_init_attr init_attr = {};
3434 struct ib_rwq_ind_table *rwq_ind_tbl;
3435 struct ib_wq **wqs = NULL;
3436 u32 *wqs_handles = NULL;
3437 struct ib_wq *wq = NULL;
3438 int i, j, num_read_wqs;
3439 u32 num_wq_handles;
3440 u32 expected_in_size;
3441 size_t required_cmd_sz_header;
3442 size_t required_resp_len;
3443
3444 required_cmd_sz_header = offsetof(typeof(cmd), log_ind_tbl_size) + sizeof(cmd.log_ind_tbl_size);
3445 required_resp_len = offsetof(typeof(resp), ind_tbl_num) + sizeof(resp.ind_tbl_num);
3446
3447 if (ucore->inlen < required_cmd_sz_header)
3448 return -EINVAL;
3449
3450 if (ucore->outlen < required_resp_len)
3451 return -ENOSPC;
3452
3453 err = ib_copy_from_udata(&cmd, ucore, required_cmd_sz_header);
3454 if (err)
3455 return err;
3456
3457 ucore->inbuf += required_cmd_sz_header;
3458 ucore->inlen -= required_cmd_sz_header;
3459
3460 if (cmd.comp_mask)
3461 return -EOPNOTSUPP;
3462
3463 if (cmd.log_ind_tbl_size > IB_USER_VERBS_MAX_LOG_IND_TBL_SIZE)
3464 return -EINVAL;
3465
3466 num_wq_handles = 1 << cmd.log_ind_tbl_size;
3467 expected_in_size = num_wq_handles * sizeof(__u32);
3468 if (num_wq_handles == 1)
3469 /* input size for wq handles is u64 aligned */
3470 expected_in_size += sizeof(__u32);
3471
3472 if (ucore->inlen < expected_in_size)
3473 return -EINVAL;
3474
3475 if (ucore->inlen > expected_in_size &&
3476 !ib_is_udata_cleared(ucore, expected_in_size,
3477 ucore->inlen - expected_in_size))
3478 return -EOPNOTSUPP;
3479
3480 wqs_handles = kcalloc(num_wq_handles, sizeof(*wqs_handles),
3481 GFP_KERNEL);
3482 if (!wqs_handles)
3483 return -ENOMEM;
3484
3485 err = ib_copy_from_udata(wqs_handles, ucore,
3486 num_wq_handles * sizeof(__u32));
3487 if (err)
3488 goto err_free;
3489
3490 wqs = kcalloc(num_wq_handles, sizeof(*wqs), GFP_KERNEL);
3491 if (!wqs) {
3492 err = -ENOMEM;
3493 goto err_free;
3494 }
3495
3496 for (num_read_wqs = 0; num_read_wqs < num_wq_handles;
3497 num_read_wqs++) {
3498 wq = idr_read_wq(wqs_handles[num_read_wqs], file->ucontext);
3499 if (!wq) {
3500 err = -EINVAL;
3501 goto put_wqs;
3502 }
3503
3504 wqs[num_read_wqs] = wq;
3505 }
3506
3507 uobj = kmalloc(sizeof(*uobj), GFP_KERNEL);
3508 if (!uobj) {
3509 err = -ENOMEM;
3510 goto put_wqs;
3511 }
3512
3513 init_uobj(uobj, 0, file->ucontext, &rwq_ind_table_lock_class);
3514 down_write(&uobj->mutex);
3515 init_attr.log_ind_tbl_size = cmd.log_ind_tbl_size;
3516 init_attr.ind_tbl = wqs;
3517 rwq_ind_tbl = ib_dev->create_rwq_ind_table(ib_dev, &init_attr, uhw);
3518
3519 if (IS_ERR(rwq_ind_tbl)) {
3520 err = PTR_ERR(rwq_ind_tbl);
3521 goto err_uobj;
3522 }
3523
3524 rwq_ind_tbl->ind_tbl = wqs;
3525 rwq_ind_tbl->log_ind_tbl_size = init_attr.log_ind_tbl_size;
3526 rwq_ind_tbl->uobject = uobj;
3527 uobj->object = rwq_ind_tbl;
3528 rwq_ind_tbl->device = ib_dev;
3529 atomic_set(&rwq_ind_tbl->usecnt, 0);
3530
3531 for (i = 0; i < num_wq_handles; i++)
3532 atomic_inc(&wqs[i]->usecnt);
3533
3534 err = idr_add_uobj(&ib_uverbs_rwq_ind_tbl_idr, uobj);
3535 if (err)
3536 goto destroy_ind_tbl;
3537
3538 resp.ind_tbl_handle = uobj->id;
3539 resp.ind_tbl_num = rwq_ind_tbl->ind_tbl_num;
3540 resp.response_length = required_resp_len;
3541
3542 err = ib_copy_to_udata(ucore,
3543 &resp, resp.response_length);
3544 if (err)
3545 goto err_copy;
3546
3547 kfree(wqs_handles);
3548
3549 for (j = 0; j < num_read_wqs; j++)
3550 put_wq_read(wqs[j]);
3551
3552 mutex_lock(&file->mutex);
3553 list_add_tail(&uobj->list, &file->ucontext->rwq_ind_tbl_list);
3554 mutex_unlock(&file->mutex);
3555
3556 uobj->live = 1;
3557
3558 up_write(&uobj->mutex);
3559 return 0;
3560
3561err_copy:
3562 idr_remove_uobj(&ib_uverbs_rwq_ind_tbl_idr, uobj);
3563destroy_ind_tbl:
3564 ib_destroy_rwq_ind_table(rwq_ind_tbl);
3565err_uobj:
3566 put_uobj_write(uobj);
3567put_wqs:
3568 for (j = 0; j < num_read_wqs; j++)
3569 put_wq_read(wqs[j]);
3570err_free:
3571 kfree(wqs_handles);
3572 kfree(wqs);
3573 return err;
3574}
3575
3576int ib_uverbs_ex_destroy_rwq_ind_table(struct ib_uverbs_file *file,
3577 struct ib_device *ib_dev,
3578 struct ib_udata *ucore,
3579 struct ib_udata *uhw)
3580{
3581 struct ib_uverbs_ex_destroy_rwq_ind_table cmd = {};
3582 struct ib_rwq_ind_table *rwq_ind_tbl;
3583 struct ib_uobject *uobj;
3584 int ret;
3585 struct ib_wq **ind_tbl;
3586 size_t required_cmd_sz;
3587
3588 required_cmd_sz = offsetof(typeof(cmd), ind_tbl_handle) + sizeof(cmd.ind_tbl_handle);
3589
3590 if (ucore->inlen < required_cmd_sz)
3591 return -EINVAL;
3592
3593 if (ucore->inlen > sizeof(cmd) &&
3594 !ib_is_udata_cleared(ucore, sizeof(cmd),
3595 ucore->inlen - sizeof(cmd)))
3596 return -EOPNOTSUPP;
3597
3598 ret = ib_copy_from_udata(&cmd, ucore, min(sizeof(cmd), ucore->inlen));
3599 if (ret)
3600 return ret;
3601
3602 if (cmd.comp_mask)
3603 return -EOPNOTSUPP;
3604
3605 uobj = idr_write_uobj(&ib_uverbs_rwq_ind_tbl_idr, cmd.ind_tbl_handle,
3606 file->ucontext);
3607 if (!uobj)
3608 return -EINVAL;
3609 rwq_ind_tbl = uobj->object;
3610 ind_tbl = rwq_ind_tbl->ind_tbl;
3611
3612 ret = ib_destroy_rwq_ind_table(rwq_ind_tbl);
3613 if (!ret)
3614 uobj->live = 0;
3615
3616 put_uobj_write(uobj);
3617
3618 if (ret)
3619 return ret;
3620
3621 idr_remove_uobj(&ib_uverbs_rwq_ind_tbl_idr, uobj);
3622
3623 mutex_lock(&file->mutex);
3624 list_del(&uobj->list);
3625 mutex_unlock(&file->mutex);
3626
3627 put_uobj(uobj);
3628 kfree(ind_tbl);
3629 return ret;
3630}
3631
Yann Droneaudf21519b2013-11-06 23:21:49 +01003632int ib_uverbs_ex_create_flow(struct ib_uverbs_file *file,
Yishai Hadas057aec02015-08-13 18:32:04 +03003633 struct ib_device *ib_dev,
Yann Droneaudf21519b2013-11-06 23:21:49 +01003634 struct ib_udata *ucore,
3635 struct ib_udata *uhw)
Hadar Hen Zion436f2ad2013-08-14 13:58:30 +03003636{
3637 struct ib_uverbs_create_flow cmd;
3638 struct ib_uverbs_create_flow_resp resp;
3639 struct ib_uobject *uobj;
3640 struct ib_flow *flow_id;
Yann Droneaudd82693d2013-11-06 23:21:45 +01003641 struct ib_uverbs_flow_attr *kern_flow_attr;
Hadar Hen Zion436f2ad2013-08-14 13:58:30 +03003642 struct ib_flow_attr *flow_attr;
3643 struct ib_qp *qp;
3644 int err = 0;
3645 void *kern_spec;
3646 void *ib_spec;
3647 int i;
Hadar Hen Zion436f2ad2013-08-14 13:58:30 +03003648
Yann Droneaud6bcca3d2013-12-11 23:01:52 +01003649 if (ucore->inlen < sizeof(cmd))
3650 return -EINVAL;
3651
Yann Droneaudf21519b2013-11-06 23:21:49 +01003652 if (ucore->outlen < sizeof(resp))
Hadar Hen Zion436f2ad2013-08-14 13:58:30 +03003653 return -ENOSPC;
3654
Yann Droneaudf21519b2013-11-06 23:21:49 +01003655 err = ib_copy_from_udata(&cmd, ucore, sizeof(cmd));
3656 if (err)
3657 return err;
3658
3659 ucore->inbuf += sizeof(cmd);
3660 ucore->inlen -= sizeof(cmd);
Hadar Hen Zion436f2ad2013-08-14 13:58:30 +03003661
Matan Barak22878db2013-09-01 18:39:52 +03003662 if (cmd.comp_mask)
3663 return -EINVAL;
3664
Christoph Lametere3b6d8c2016-05-13 10:52:26 -05003665 if (!capable(CAP_NET_RAW))
Hadar Hen Zion436f2ad2013-08-14 13:58:30 +03003666 return -EPERM;
3667
Marina Varshavera3100a72016-02-18 18:31:05 +02003668 if (cmd.flow_attr.flags >= IB_FLOW_ATTR_FLAGS_RESERVED)
3669 return -EINVAL;
3670
3671 if ((cmd.flow_attr.flags & IB_FLOW_ATTR_FLAGS_DONT_TRAP) &&
3672 ((cmd.flow_attr.type == IB_FLOW_ATTR_ALL_DEFAULT) ||
3673 (cmd.flow_attr.type == IB_FLOW_ATTR_MC_DEFAULT)))
3674 return -EINVAL;
3675
Matan Barakf8848272013-11-06 23:21:44 +01003676 if (cmd.flow_attr.num_of_specs > IB_FLOW_SPEC_SUPPORT_LAYERS)
Matan Barak22878db2013-09-01 18:39:52 +03003677 return -EINVAL;
3678
Yann Droneaudf21519b2013-11-06 23:21:49 +01003679 if (cmd.flow_attr.size > ucore->inlen ||
Matan Barakf8848272013-11-06 23:21:44 +01003680 cmd.flow_attr.size >
Yann Droneaudb68c9562013-11-06 23:21:46 +01003681 (cmd.flow_attr.num_of_specs * sizeof(struct ib_uverbs_flow_spec)))
Matan Barak22878db2013-09-01 18:39:52 +03003682 return -EINVAL;
3683
Yann Droneaudc780d822013-12-11 23:01:49 +01003684 if (cmd.flow_attr.reserved[0] ||
3685 cmd.flow_attr.reserved[1])
3686 return -EINVAL;
3687
Hadar Hen Zion436f2ad2013-08-14 13:58:30 +03003688 if (cmd.flow_attr.num_of_specs) {
Matan Barakf8848272013-11-06 23:21:44 +01003689 kern_flow_attr = kmalloc(sizeof(*kern_flow_attr) + cmd.flow_attr.size,
3690 GFP_KERNEL);
Hadar Hen Zion436f2ad2013-08-14 13:58:30 +03003691 if (!kern_flow_attr)
3692 return -ENOMEM;
3693
3694 memcpy(kern_flow_attr, &cmd.flow_attr, sizeof(*kern_flow_attr));
Yann Droneaudf21519b2013-11-06 23:21:49 +01003695 err = ib_copy_from_udata(kern_flow_attr + 1, ucore,
3696 cmd.flow_attr.size);
3697 if (err)
Hadar Hen Zion436f2ad2013-08-14 13:58:30 +03003698 goto err_free_attr;
Hadar Hen Zion436f2ad2013-08-14 13:58:30 +03003699 } else {
3700 kern_flow_attr = &cmd.flow_attr;
Hadar Hen Zion436f2ad2013-08-14 13:58:30 +03003701 }
3702
3703 uobj = kmalloc(sizeof(*uobj), GFP_KERNEL);
3704 if (!uobj) {
3705 err = -ENOMEM;
3706 goto err_free_attr;
3707 }
3708 init_uobj(uobj, 0, file->ucontext, &rule_lock_class);
3709 down_write(&uobj->mutex);
3710
3711 qp = idr_read_qp(cmd.qp_handle, file->ucontext);
3712 if (!qp) {
3713 err = -EINVAL;
3714 goto err_uobj;
3715 }
3716
Maor Gottlieb15dfbd62016-08-30 16:58:32 +03003717 flow_attr = kzalloc(sizeof(*flow_attr) + cmd.flow_attr.num_of_specs *
3718 sizeof(union ib_flow_spec), GFP_KERNEL);
Hadar Hen Zion436f2ad2013-08-14 13:58:30 +03003719 if (!flow_attr) {
3720 err = -ENOMEM;
3721 goto err_put;
3722 }
3723
3724 flow_attr->type = kern_flow_attr->type;
3725 flow_attr->priority = kern_flow_attr->priority;
3726 flow_attr->num_of_specs = kern_flow_attr->num_of_specs;
3727 flow_attr->port = kern_flow_attr->port;
3728 flow_attr->flags = kern_flow_attr->flags;
3729 flow_attr->size = sizeof(*flow_attr);
3730
3731 kern_spec = kern_flow_attr + 1;
3732 ib_spec = flow_attr + 1;
Matan Barakf8848272013-11-06 23:21:44 +01003733 for (i = 0; i < flow_attr->num_of_specs &&
Yann Droneaudb68c9562013-11-06 23:21:46 +01003734 cmd.flow_attr.size > offsetof(struct ib_uverbs_flow_spec, reserved) &&
Matan Barakf8848272013-11-06 23:21:44 +01003735 cmd.flow_attr.size >=
Yann Droneaudb68c9562013-11-06 23:21:46 +01003736 ((struct ib_uverbs_flow_spec *)kern_spec)->size; i++) {
Hadar Hen Zion436f2ad2013-08-14 13:58:30 +03003737 err = kern_spec_to_ib_spec(kern_spec, ib_spec);
3738 if (err)
3739 goto err_free;
3740 flow_attr->size +=
3741 ((union ib_flow_spec *) ib_spec)->size;
Yann Droneaudb68c9562013-11-06 23:21:46 +01003742 cmd.flow_attr.size -= ((struct ib_uverbs_flow_spec *)kern_spec)->size;
3743 kern_spec += ((struct ib_uverbs_flow_spec *) kern_spec)->size;
Hadar Hen Zion436f2ad2013-08-14 13:58:30 +03003744 ib_spec += ((union ib_flow_spec *) ib_spec)->size;
3745 }
Matan Barakf8848272013-11-06 23:21:44 +01003746 if (cmd.flow_attr.size || (i != flow_attr->num_of_specs)) {
3747 pr_warn("create flow failed, flow %d: %d bytes left from uverb cmd\n",
3748 i, cmd.flow_attr.size);
Yann Droneaud98a37512013-12-11 23:01:50 +01003749 err = -EINVAL;
Hadar Hen Zion436f2ad2013-08-14 13:58:30 +03003750 goto err_free;
3751 }
3752 flow_id = ib_create_flow(qp, flow_attr, IB_FLOW_DOMAIN_USER);
3753 if (IS_ERR(flow_id)) {
3754 err = PTR_ERR(flow_id);
3755 goto err_free;
3756 }
3757 flow_id->qp = qp;
3758 flow_id->uobject = uobj;
3759 uobj->object = flow_id;
3760
3761 err = idr_add_uobj(&ib_uverbs_rule_idr, uobj);
3762 if (err)
3763 goto destroy_flow;
3764
3765 memset(&resp, 0, sizeof(resp));
3766 resp.flow_handle = uobj->id;
3767
Yann Droneaudf21519b2013-11-06 23:21:49 +01003768 err = ib_copy_to_udata(ucore,
3769 &resp, sizeof(resp));
3770 if (err)
Hadar Hen Zion436f2ad2013-08-14 13:58:30 +03003771 goto err_copy;
Hadar Hen Zion436f2ad2013-08-14 13:58:30 +03003772
3773 put_qp_read(qp);
3774 mutex_lock(&file->mutex);
3775 list_add_tail(&uobj->list, &file->ucontext->rule_list);
3776 mutex_unlock(&file->mutex);
3777
3778 uobj->live = 1;
3779
3780 up_write(&uobj->mutex);
3781 kfree(flow_attr);
3782 if (cmd.flow_attr.num_of_specs)
3783 kfree(kern_flow_attr);
Yann Droneaudf21519b2013-11-06 23:21:49 +01003784 return 0;
Hadar Hen Zion436f2ad2013-08-14 13:58:30 +03003785err_copy:
3786 idr_remove_uobj(&ib_uverbs_rule_idr, uobj);
3787destroy_flow:
3788 ib_destroy_flow(flow_id);
3789err_free:
3790 kfree(flow_attr);
3791err_put:
3792 put_qp_read(qp);
3793err_uobj:
3794 put_uobj_write(uobj);
3795err_free_attr:
3796 if (cmd.flow_attr.num_of_specs)
3797 kfree(kern_flow_attr);
3798 return err;
3799}
3800
Yann Droneaudf21519b2013-11-06 23:21:49 +01003801int ib_uverbs_ex_destroy_flow(struct ib_uverbs_file *file,
Yishai Hadas057aec02015-08-13 18:32:04 +03003802 struct ib_device *ib_dev,
Yann Droneaudf21519b2013-11-06 23:21:49 +01003803 struct ib_udata *ucore,
3804 struct ib_udata *uhw)
3805{
Hadar Hen Zion436f2ad2013-08-14 13:58:30 +03003806 struct ib_uverbs_destroy_flow cmd;
3807 struct ib_flow *flow_id;
3808 struct ib_uobject *uobj;
3809 int ret;
3810
Yann Droneaud6bcca3d2013-12-11 23:01:52 +01003811 if (ucore->inlen < sizeof(cmd))
3812 return -EINVAL;
3813
Yann Droneaudf21519b2013-11-06 23:21:49 +01003814 ret = ib_copy_from_udata(&cmd, ucore, sizeof(cmd));
3815 if (ret)
3816 return ret;
Hadar Hen Zion436f2ad2013-08-14 13:58:30 +03003817
Yann Droneaud2782c2d2013-12-11 23:01:48 +01003818 if (cmd.comp_mask)
3819 return -EINVAL;
3820
Hadar Hen Zion436f2ad2013-08-14 13:58:30 +03003821 uobj = idr_write_uobj(&ib_uverbs_rule_idr, cmd.flow_handle,
3822 file->ucontext);
3823 if (!uobj)
3824 return -EINVAL;
3825 flow_id = uobj->object;
3826
3827 ret = ib_destroy_flow(flow_id);
3828 if (!ret)
3829 uobj->live = 0;
3830
3831 put_uobj_write(uobj);
3832
3833 idr_remove_uobj(&ib_uverbs_rule_idr, uobj);
3834
3835 mutex_lock(&file->mutex);
3836 list_del(&uobj->list);
3837 mutex_unlock(&file->mutex);
3838
3839 put_uobj(uobj);
3840
Yann Droneaudf21519b2013-11-06 23:21:49 +01003841 return ret;
Hadar Hen Zion436f2ad2013-08-14 13:58:30 +03003842}
3843
Sean Heftyc89d1be2011-12-06 21:13:10 +00003844static int __uverbs_create_xsrq(struct ib_uverbs_file *file,
Yishai Hadas057aec02015-08-13 18:32:04 +03003845 struct ib_device *ib_dev,
Sean Heftyc89d1be2011-12-06 21:13:10 +00003846 struct ib_uverbs_create_xsrq *cmd,
3847 struct ib_udata *udata)
Sean Hefty8541f8d2011-05-25 17:08:38 -07003848{
3849 struct ib_uverbs_create_srq_resp resp;
3850 struct ib_usrq_object *obj;
3851 struct ib_pd *pd;
3852 struct ib_srq *srq;
3853 struct ib_uobject *uninitialized_var(xrcd_uobj);
3854 struct ib_srq_init_attr attr;
3855 int ret;
3856
3857 obj = kmalloc(sizeof *obj, GFP_KERNEL);
3858 if (!obj)
3859 return -ENOMEM;
3860
Roland Dreier3bea57a2012-04-30 10:27:26 -07003861 init_uobj(&obj->uevent.uobject, cmd->user_handle, file->ucontext, &srq_lock_class);
Sean Hefty8541f8d2011-05-25 17:08:38 -07003862 down_write(&obj->uevent.uobject.mutex);
3863
Sean Hefty8541f8d2011-05-25 17:08:38 -07003864 if (cmd->srq_type == IB_SRQT_XRC) {
Sean Hefty8541f8d2011-05-25 17:08:38 -07003865 attr.ext.xrc.xrcd = idr_read_xrcd(cmd->xrcd_handle, file->ucontext, &xrcd_uobj);
3866 if (!attr.ext.xrc.xrcd) {
3867 ret = -EINVAL;
Roland Dreier5909ce52012-04-30 12:51:50 -07003868 goto err;
Sean Hefty8541f8d2011-05-25 17:08:38 -07003869 }
3870
3871 obj->uxrcd = container_of(xrcd_uobj, struct ib_uxrcd_object, uobject);
3872 atomic_inc(&obj->uxrcd->refcnt);
Roland Dreier5909ce52012-04-30 12:51:50 -07003873
3874 attr.ext.xrc.cq = idr_read_cq(cmd->cq_handle, file->ucontext, 0);
3875 if (!attr.ext.xrc.cq) {
3876 ret = -EINVAL;
3877 goto err_put_xrcd;
3878 }
3879 }
3880
3881 pd = idr_read_pd(cmd->pd_handle, file->ucontext);
3882 if (!pd) {
3883 ret = -EINVAL;
3884 goto err_put_cq;
Sean Hefty8541f8d2011-05-25 17:08:38 -07003885 }
3886
3887 attr.event_handler = ib_uverbs_srq_event_handler;
3888 attr.srq_context = file;
3889 attr.srq_type = cmd->srq_type;
3890 attr.attr.max_wr = cmd->max_wr;
3891 attr.attr.max_sge = cmd->max_sge;
3892 attr.attr.srq_limit = cmd->srq_limit;
3893
3894 obj->uevent.events_reported = 0;
3895 INIT_LIST_HEAD(&obj->uevent.event_list);
3896
3897 srq = pd->device->create_srq(pd, &attr, udata);
3898 if (IS_ERR(srq)) {
3899 ret = PTR_ERR(srq);
3900 goto err_put;
3901 }
3902
3903 srq->device = pd->device;
3904 srq->pd = pd;
3905 srq->srq_type = cmd->srq_type;
3906 srq->uobject = &obj->uevent.uobject;
3907 srq->event_handler = attr.event_handler;
3908 srq->srq_context = attr.srq_context;
3909
3910 if (cmd->srq_type == IB_SRQT_XRC) {
3911 srq->ext.xrc.cq = attr.ext.xrc.cq;
3912 srq->ext.xrc.xrcd = attr.ext.xrc.xrcd;
3913 atomic_inc(&attr.ext.xrc.cq->usecnt);
3914 atomic_inc(&attr.ext.xrc.xrcd->usecnt);
3915 }
3916
3917 atomic_inc(&pd->usecnt);
3918 atomic_set(&srq->usecnt, 0);
3919
3920 obj->uevent.uobject.object = srq;
3921 ret = idr_add_uobj(&ib_uverbs_srq_idr, &obj->uevent.uobject);
3922 if (ret)
3923 goto err_destroy;
3924
3925 memset(&resp, 0, sizeof resp);
3926 resp.srq_handle = obj->uevent.uobject.id;
3927 resp.max_wr = attr.attr.max_wr;
3928 resp.max_sge = attr.attr.max_sge;
3929 if (cmd->srq_type == IB_SRQT_XRC)
3930 resp.srqn = srq->ext.xrc.srq_num;
3931
3932 if (copy_to_user((void __user *) (unsigned long) cmd->response,
3933 &resp, sizeof resp)) {
3934 ret = -EFAULT;
3935 goto err_copy;
3936 }
3937
3938 if (cmd->srq_type == IB_SRQT_XRC) {
3939 put_uobj_read(xrcd_uobj);
3940 put_cq_read(attr.ext.xrc.cq);
3941 }
3942 put_pd_read(pd);
3943
3944 mutex_lock(&file->mutex);
3945 list_add_tail(&obj->uevent.uobject.list, &file->ucontext->srq_list);
3946 mutex_unlock(&file->mutex);
3947
3948 obj->uevent.uobject.live = 1;
3949
3950 up_write(&obj->uevent.uobject.mutex);
3951
3952 return 0;
3953
3954err_copy:
3955 idr_remove_uobj(&ib_uverbs_srq_idr, &obj->uevent.uobject);
3956
3957err_destroy:
3958 ib_destroy_srq(srq);
3959
3960err_put:
Roland Dreier5909ce52012-04-30 12:51:50 -07003961 put_pd_read(pd);
Sean Hefty8541f8d2011-05-25 17:08:38 -07003962
3963err_put_cq:
3964 if (cmd->srq_type == IB_SRQT_XRC)
3965 put_cq_read(attr.ext.xrc.cq);
3966
Roland Dreier5909ce52012-04-30 12:51:50 -07003967err_put_xrcd:
3968 if (cmd->srq_type == IB_SRQT_XRC) {
3969 atomic_dec(&obj->uxrcd->refcnt);
3970 put_uobj_read(xrcd_uobj);
3971 }
Sean Hefty8541f8d2011-05-25 17:08:38 -07003972
3973err:
3974 put_uobj_write(&obj->uevent.uobject);
3975 return ret;
3976}
3977
Roland Dreierf520ba52005-08-18 12:24:13 -07003978ssize_t ib_uverbs_create_srq(struct ib_uverbs_file *file,
Yishai Hadas057aec02015-08-13 18:32:04 +03003979 struct ib_device *ib_dev,
Roland Dreierf520ba52005-08-18 12:24:13 -07003980 const char __user *buf, int in_len,
3981 int out_len)
3982{
3983 struct ib_uverbs_create_srq cmd;
Sean Hefty8541f8d2011-05-25 17:08:38 -07003984 struct ib_uverbs_create_xsrq xcmd;
Roland Dreierf520ba52005-08-18 12:24:13 -07003985 struct ib_uverbs_create_srq_resp resp;
3986 struct ib_udata udata;
Sean Hefty8541f8d2011-05-25 17:08:38 -07003987 int ret;
3988
3989 if (out_len < sizeof resp)
3990 return -ENOSPC;
3991
3992 if (copy_from_user(&cmd, buf, sizeof cmd))
3993 return -EFAULT;
3994
3995 xcmd.response = cmd.response;
3996 xcmd.user_handle = cmd.user_handle;
3997 xcmd.srq_type = IB_SRQT_BASIC;
3998 xcmd.pd_handle = cmd.pd_handle;
3999 xcmd.max_wr = cmd.max_wr;
4000 xcmd.max_sge = cmd.max_sge;
4001 xcmd.srq_limit = cmd.srq_limit;
4002
4003 INIT_UDATA(&udata, buf + sizeof cmd,
4004 (unsigned long) cmd.response + sizeof resp,
Majd Dibbiny3d943c92016-02-14 18:35:52 +02004005 in_len - sizeof cmd - sizeof(struct ib_uverbs_cmd_hdr),
4006 out_len - sizeof resp);
Sean Hefty8541f8d2011-05-25 17:08:38 -07004007
Yishai Hadas057aec02015-08-13 18:32:04 +03004008 ret = __uverbs_create_xsrq(file, ib_dev, &xcmd, &udata);
Sean Hefty8541f8d2011-05-25 17:08:38 -07004009 if (ret)
4010 return ret;
4011
4012 return in_len;
4013}
4014
4015ssize_t ib_uverbs_create_xsrq(struct ib_uverbs_file *file,
Yishai Hadas057aec02015-08-13 18:32:04 +03004016 struct ib_device *ib_dev,
Sean Hefty8541f8d2011-05-25 17:08:38 -07004017 const char __user *buf, int in_len, int out_len)
4018{
4019 struct ib_uverbs_create_xsrq cmd;
4020 struct ib_uverbs_create_srq_resp resp;
4021 struct ib_udata udata;
Roland Dreierf520ba52005-08-18 12:24:13 -07004022 int ret;
4023
4024 if (out_len < sizeof resp)
4025 return -ENOSPC;
4026
4027 if (copy_from_user(&cmd, buf, sizeof cmd))
4028 return -EFAULT;
4029
4030 INIT_UDATA(&udata, buf + sizeof cmd,
4031 (unsigned long) cmd.response + sizeof resp,
Majd Dibbiny3d943c92016-02-14 18:35:52 +02004032 in_len - sizeof cmd - sizeof(struct ib_uverbs_cmd_hdr),
4033 out_len - sizeof resp);
Roland Dreierf520ba52005-08-18 12:24:13 -07004034
Yishai Hadas057aec02015-08-13 18:32:04 +03004035 ret = __uverbs_create_xsrq(file, ib_dev, &cmd, &udata);
Roland Dreierf520ba52005-08-18 12:24:13 -07004036 if (ret)
Sean Hefty8541f8d2011-05-25 17:08:38 -07004037 return ret;
Roland Dreierf520ba52005-08-18 12:24:13 -07004038
4039 return in_len;
Roland Dreierf520ba52005-08-18 12:24:13 -07004040}
4041
4042ssize_t ib_uverbs_modify_srq(struct ib_uverbs_file *file,
Yishai Hadas057aec02015-08-13 18:32:04 +03004043 struct ib_device *ib_dev,
Roland Dreierf520ba52005-08-18 12:24:13 -07004044 const char __user *buf, int in_len,
4045 int out_len)
4046{
4047 struct ib_uverbs_modify_srq cmd;
Ralph Campbell9bc57e22006-08-11 14:58:09 -07004048 struct ib_udata udata;
Roland Dreierf520ba52005-08-18 12:24:13 -07004049 struct ib_srq *srq;
4050 struct ib_srq_attr attr;
4051 int ret;
4052
4053 if (copy_from_user(&cmd, buf, sizeof cmd))
4054 return -EFAULT;
4055
Ralph Campbell9bc57e22006-08-11 14:58:09 -07004056 INIT_UDATA(&udata, buf + sizeof cmd, NULL, in_len - sizeof cmd,
4057 out_len);
4058
Roland Dreier9ead1902006-06-17 20:44:49 -07004059 srq = idr_read_srq(cmd.srq_handle, file->ucontext);
4060 if (!srq)
4061 return -EINVAL;
Roland Dreierf520ba52005-08-18 12:24:13 -07004062
4063 attr.max_wr = cmd.max_wr;
Roland Dreierf520ba52005-08-18 12:24:13 -07004064 attr.srq_limit = cmd.srq_limit;
4065
Ralph Campbell9bc57e22006-08-11 14:58:09 -07004066 ret = srq->device->modify_srq(srq, &attr, cmd.attr_mask, &udata);
Roland Dreierf520ba52005-08-18 12:24:13 -07004067
Roland Dreier9ead1902006-06-17 20:44:49 -07004068 put_srq_read(srq);
Roland Dreierf520ba52005-08-18 12:24:13 -07004069
4070 return ret ? ret : in_len;
4071}
4072
Dotan Barak8bdb0e82006-02-13 16:31:57 -08004073ssize_t ib_uverbs_query_srq(struct ib_uverbs_file *file,
Yishai Hadas057aec02015-08-13 18:32:04 +03004074 struct ib_device *ib_dev,
Dotan Barak8bdb0e82006-02-13 16:31:57 -08004075 const char __user *buf,
4076 int in_len, int out_len)
4077{
4078 struct ib_uverbs_query_srq cmd;
4079 struct ib_uverbs_query_srq_resp resp;
4080 struct ib_srq_attr attr;
4081 struct ib_srq *srq;
4082 int ret;
4083
4084 if (out_len < sizeof resp)
4085 return -ENOSPC;
4086
4087 if (copy_from_user(&cmd, buf, sizeof cmd))
4088 return -EFAULT;
4089
Roland Dreier9ead1902006-06-17 20:44:49 -07004090 srq = idr_read_srq(cmd.srq_handle, file->ucontext);
4091 if (!srq)
4092 return -EINVAL;
Dotan Barak8bdb0e82006-02-13 16:31:57 -08004093
Roland Dreier9ead1902006-06-17 20:44:49 -07004094 ret = ib_query_srq(srq, &attr);
Dotan Barak8bdb0e82006-02-13 16:31:57 -08004095
Roland Dreier9ead1902006-06-17 20:44:49 -07004096 put_srq_read(srq);
Dotan Barak8bdb0e82006-02-13 16:31:57 -08004097
4098 if (ret)
Roland Dreier9ead1902006-06-17 20:44:49 -07004099 return ret;
Dotan Barak8bdb0e82006-02-13 16:31:57 -08004100
4101 memset(&resp, 0, sizeof resp);
4102
4103 resp.max_wr = attr.max_wr;
4104 resp.max_sge = attr.max_sge;
4105 resp.srq_limit = attr.srq_limit;
4106
4107 if (copy_to_user((void __user *) (unsigned long) cmd.response,
4108 &resp, sizeof resp))
Roland Dreier9ead1902006-06-17 20:44:49 -07004109 return -EFAULT;
Dotan Barak8bdb0e82006-02-13 16:31:57 -08004110
Roland Dreier9ead1902006-06-17 20:44:49 -07004111 return in_len;
Dotan Barak8bdb0e82006-02-13 16:31:57 -08004112}
4113
Roland Dreierf520ba52005-08-18 12:24:13 -07004114ssize_t ib_uverbs_destroy_srq(struct ib_uverbs_file *file,
Yishai Hadas057aec02015-08-13 18:32:04 +03004115 struct ib_device *ib_dev,
Roland Dreierf520ba52005-08-18 12:24:13 -07004116 const char __user *buf, int in_len,
4117 int out_len)
4118{
Roland Dreier63aaf642005-09-09 15:55:08 -07004119 struct ib_uverbs_destroy_srq cmd;
4120 struct ib_uverbs_destroy_srq_resp resp;
Roland Dreier9ead1902006-06-17 20:44:49 -07004121 struct ib_uobject *uobj;
Roland Dreier63aaf642005-09-09 15:55:08 -07004122 struct ib_srq *srq;
Roland Dreier9ead1902006-06-17 20:44:49 -07004123 struct ib_uevent_object *obj;
Roland Dreier63aaf642005-09-09 15:55:08 -07004124 int ret = -EINVAL;
Yishai Hadas846be902013-08-01 18:49:54 +03004125 struct ib_usrq_object *us;
4126 enum ib_srq_type srq_type;
Roland Dreierf520ba52005-08-18 12:24:13 -07004127
4128 if (copy_from_user(&cmd, buf, sizeof cmd))
4129 return -EFAULT;
4130
Roland Dreier9ead1902006-06-17 20:44:49 -07004131 uobj = idr_write_uobj(&ib_uverbs_srq_idr, cmd.srq_handle, file->ucontext);
4132 if (!uobj)
4133 return -EINVAL;
4134 srq = uobj->object;
4135 obj = container_of(uobj, struct ib_uevent_object, uobject);
Yishai Hadas846be902013-08-01 18:49:54 +03004136 srq_type = srq->srq_type;
Roland Dreierf520ba52005-08-18 12:24:13 -07004137
4138 ret = ib_destroy_srq(srq);
Roland Dreier9ead1902006-06-17 20:44:49 -07004139 if (!ret)
4140 uobj->live = 0;
Roland Dreierf520ba52005-08-18 12:24:13 -07004141
Roland Dreier9ead1902006-06-17 20:44:49 -07004142 put_uobj_write(uobj);
4143
4144 if (ret)
4145 return ret;
4146
Yishai Hadas846be902013-08-01 18:49:54 +03004147 if (srq_type == IB_SRQT_XRC) {
4148 us = container_of(obj, struct ib_usrq_object, uevent);
4149 atomic_dec(&us->uxrcd->refcnt);
4150 }
4151
Roland Dreier9ead1902006-06-17 20:44:49 -07004152 idr_remove_uobj(&ib_uverbs_srq_idr, uobj);
Roland Dreierf520ba52005-08-18 12:24:13 -07004153
Ingo Molnar95ed6442006-01-13 14:51:39 -08004154 mutex_lock(&file->mutex);
Roland Dreier9ead1902006-06-17 20:44:49 -07004155 list_del(&uobj->list);
Ingo Molnar95ed6442006-01-13 14:51:39 -08004156 mutex_unlock(&file->mutex);
Roland Dreierf520ba52005-08-18 12:24:13 -07004157
Roland Dreier9ead1902006-06-17 20:44:49 -07004158 ib_uverbs_release_uevent(file, obj);
Roland Dreier63aaf642005-09-09 15:55:08 -07004159
Roland Dreier9ead1902006-06-17 20:44:49 -07004160 memset(&resp, 0, sizeof resp);
4161 resp.events_reported = obj->events_reported;
Roland Dreier63aaf642005-09-09 15:55:08 -07004162
Roland Dreier9ead1902006-06-17 20:44:49 -07004163 put_uobj(uobj);
Roland Dreierf520ba52005-08-18 12:24:13 -07004164
Roland Dreier63aaf642005-09-09 15:55:08 -07004165 if (copy_to_user((void __user *) (unsigned long) cmd.response,
4166 &resp, sizeof resp))
4167 ret = -EFAULT;
4168
Roland Dreierf520ba52005-08-18 12:24:13 -07004169 return ret ? ret : in_len;
4170}
Eli Cohen02d1aa72015-02-08 13:28:50 +02004171
4172int ib_uverbs_ex_query_device(struct ib_uverbs_file *file,
Yishai Hadas057aec02015-08-13 18:32:04 +03004173 struct ib_device *ib_dev,
Eli Cohen02d1aa72015-02-08 13:28:50 +02004174 struct ib_udata *ucore,
4175 struct ib_udata *uhw)
4176{
Leon Romanovsky2953f422016-02-23 10:25:24 +02004177 struct ib_uverbs_ex_query_device_resp resp = { {0} };
Eli Cohen02d1aa72015-02-08 13:28:50 +02004178 struct ib_uverbs_ex_query_device cmd;
Leon Romanovsky2953f422016-02-23 10:25:24 +02004179 struct ib_device_attr attr = {0};
Eli Cohen02d1aa72015-02-08 13:28:50 +02004180 int err;
4181
Eli Cohen02d1aa72015-02-08 13:28:50 +02004182 if (ucore->inlen < sizeof(cmd))
4183 return -EINVAL;
4184
4185 err = ib_copy_from_udata(&cmd, ucore, sizeof(cmd));
4186 if (err)
4187 return err;
4188
4189 if (cmd.comp_mask)
4190 return -EINVAL;
4191
4192 if (cmd.reserved)
4193 return -EINVAL;
4194
Haggai Eranf4056bf2015-02-08 13:28:51 +02004195 resp.response_length = offsetof(typeof(resp), odp_caps);
Eli Cohen02d1aa72015-02-08 13:28:50 +02004196
4197 if (ucore->outlen < resp.response_length)
4198 return -ENOSPC;
4199
Yishai Hadas057aec02015-08-13 18:32:04 +03004200 err = ib_dev->query_device(ib_dev, &attr, uhw);
Eli Cohen02d1aa72015-02-08 13:28:50 +02004201 if (err)
4202 return err;
4203
Yishai Hadas057aec02015-08-13 18:32:04 +03004204 copy_query_dev_fields(file, ib_dev, &resp.base, &attr);
Eli Cohen02d1aa72015-02-08 13:28:50 +02004205
Haggai Eranf4056bf2015-02-08 13:28:51 +02004206 if (ucore->outlen < resp.response_length + sizeof(resp.odp_caps))
4207 goto end;
4208
4209#ifdef CONFIG_INFINIBAND_ON_DEMAND_PAGING
4210 resp.odp_caps.general_caps = attr.odp_caps.general_caps;
4211 resp.odp_caps.per_transport_caps.rc_odp_caps =
4212 attr.odp_caps.per_transport_caps.rc_odp_caps;
4213 resp.odp_caps.per_transport_caps.uc_odp_caps =
4214 attr.odp_caps.per_transport_caps.uc_odp_caps;
4215 resp.odp_caps.per_transport_caps.ud_odp_caps =
4216 attr.odp_caps.per_transport_caps.ud_odp_caps;
Haggai Eranf4056bf2015-02-08 13:28:51 +02004217#endif
4218 resp.response_length += sizeof(resp.odp_caps);
4219
Matan Barak24306dc2015-06-11 16:35:24 +03004220 if (ucore->outlen < resp.response_length + sizeof(resp.timestamp_mask))
4221 goto end;
4222
4223 resp.timestamp_mask = attr.timestamp_mask;
4224 resp.response_length += sizeof(resp.timestamp_mask);
4225
4226 if (ucore->outlen < resp.response_length + sizeof(resp.hca_core_clock))
4227 goto end;
4228
4229 resp.hca_core_clock = attr.hca_core_clock;
4230 resp.response_length += sizeof(resp.hca_core_clock);
4231
Majd Dibbiny0b24e5a2016-04-17 17:19:34 +03004232 if (ucore->outlen < resp.response_length + sizeof(resp.device_cap_flags_ex))
4233 goto end;
4234
4235 resp.device_cap_flags_ex = attr.device_cap_flags;
4236 resp.response_length += sizeof(resp.device_cap_flags_ex);
Yishai Hadas47adf2f2016-08-28 11:28:44 +03004237
4238 if (ucore->outlen < resp.response_length + sizeof(resp.rss_caps))
4239 goto end;
4240
4241 resp.rss_caps.supported_qpts = attr.rss_caps.supported_qpts;
4242 resp.rss_caps.max_rwq_indirection_tables =
4243 attr.rss_caps.max_rwq_indirection_tables;
4244 resp.rss_caps.max_rwq_indirection_table_size =
4245 attr.rss_caps.max_rwq_indirection_table_size;
4246
4247 resp.response_length += sizeof(resp.rss_caps);
4248
4249 if (ucore->outlen < resp.response_length + sizeof(resp.max_wq_type_rq))
4250 goto end;
4251
4252 resp.max_wq_type_rq = attr.max_wq_type_rq;
4253 resp.response_length += sizeof(resp.max_wq_type_rq);
Haggai Eranf4056bf2015-02-08 13:28:51 +02004254end:
Eli Cohen02d1aa72015-02-08 13:28:50 +02004255 err = ib_copy_to_udata(ucore, &resp, resp.response_length);
Leon Romanovsky2953f422016-02-23 10:25:24 +02004256 return err;
Eli Cohen02d1aa72015-02-08 13:28:50 +02004257}