blob: c29a660c72fe3674cea593f9cdab483f133edd8f [file] [log] [blame]
Roland Dreierbc38a6a2005-07-07 17:57:13 -07001/*
2 * Copyright (c) 2005 Topspin Communications. All rights reserved.
Roland Dreier33b9b3e2006-01-30 14:29:21 -08003 * Copyright (c) 2005, 2006 Cisco Systems. All rights reserved.
Roland Dreier2a1d9b72005-08-10 23:03:10 -07004 * Copyright (c) 2005 Mellanox Technologies. All rights reserved.
5 * Copyright (c) 2005 Voltaire, Inc. All rights reserved.
Roland Dreier67cdb402005-10-14 15:26:04 -07006 * Copyright (c) 2005 PathScale, Inc. All rights reserved.
Roland Dreierbc38a6a2005-07-07 17:57:13 -07007 *
8 * This software is available to you under a choice of one of two
9 * licenses. You may choose to be licensed under the terms of the GNU
10 * General Public License (GPL) Version 2, available from the file
11 * COPYING in the main directory of this source tree, or the
12 * OpenIB.org BSD license below:
13 *
14 * Redistribution and use in source and binary forms, with or
15 * without modification, are permitted provided that the following
16 * conditions are met:
17 *
18 * - Redistributions of source code must retain the above
19 * copyright notice, this list of conditions and the following
20 * disclaimer.
21 *
22 * - Redistributions in binary form must reproduce the above
23 * copyright notice, this list of conditions and the following
24 * disclaimer in the documentation and/or other materials
25 * provided with the distribution.
26 *
27 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
28 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
29 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
30 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
31 * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
32 * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
33 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
34 * SOFTWARE.
Roland Dreierbc38a6a2005-07-07 17:57:13 -070035 */
36
37#include <linux/module.h>
38#include <linux/init.h>
39#include <linux/device.h>
40#include <linux/err.h>
41#include <linux/fs.h>
42#include <linux/poll.h>
Alexey Dobriyana99bbaf2009-10-04 16:11:37 +040043#include <linux/sched.h>
Roland Dreierbc38a6a2005-07-07 17:57:13 -070044#include <linux/file.h>
Roland Dreier70a30e12005-10-28 15:38:26 -070045#include <linux/cdev.h>
Roland Dreiera265e552010-02-24 16:51:20 -080046#include <linux/anon_inodes.h>
Tejun Heo5a0e3ad2010-03-24 17:04:11 +090047#include <linux/slab.h>
Roland Dreierbc38a6a2005-07-07 17:57:13 -070048
49#include <asm/uaccess.h>
50
51#include "uverbs.h"
52
53MODULE_AUTHOR("Roland Dreier");
54MODULE_DESCRIPTION("InfiniBand userspace verbs access");
55MODULE_LICENSE("Dual BSD/GPL");
56
Roland Dreierbc38a6a2005-07-07 17:57:13 -070057enum {
58 IB_UVERBS_MAJOR = 231,
59 IB_UVERBS_BASE_MINOR = 192,
60 IB_UVERBS_MAX_DEVICES = 32
61};
62
63#define IB_UVERBS_BASE_DEV MKDEV(IB_UVERBS_MAJOR, IB_UVERBS_BASE_MINOR)
64
Roland Dreier70a30e12005-10-28 15:38:26 -070065static struct class *uverbs_class;
66
Roland Dreier9ead1902006-06-17 20:44:49 -070067DEFINE_SPINLOCK(ib_uverbs_idr_lock);
Roland Dreierbc38a6a2005-07-07 17:57:13 -070068DEFINE_IDR(ib_uverbs_pd_idr);
69DEFINE_IDR(ib_uverbs_mr_idr);
70DEFINE_IDR(ib_uverbs_mw_idr);
71DEFINE_IDR(ib_uverbs_ah_idr);
72DEFINE_IDR(ib_uverbs_cq_idr);
73DEFINE_IDR(ib_uverbs_qp_idr);
Roland Dreierf520ba52005-08-18 12:24:13 -070074DEFINE_IDR(ib_uverbs_srq_idr);
Sean Hefty53d0bd12011-05-24 08:33:46 -070075DEFINE_IDR(ib_uverbs_xrcd_idr);
Hadar Hen Zion436f2ad2013-08-14 13:58:30 +030076DEFINE_IDR(ib_uverbs_rule_idr);
Roland Dreierbc38a6a2005-07-07 17:57:13 -070077
Roland Dreier6276e082009-09-05 20:24:23 -070078static DEFINE_SPINLOCK(map_lock);
Roland Dreierbc38a6a2005-07-07 17:57:13 -070079static DECLARE_BITMAP(dev_map, IB_UVERBS_MAX_DEVICES);
80
81static ssize_t (*uverbs_cmd_table[])(struct ib_uverbs_file *file,
Yishai Hadas057aec02015-08-13 18:32:04 +030082 struct ib_device *ib_dev,
Roland Dreierbc38a6a2005-07-07 17:57:13 -070083 const char __user *buf, int in_len,
84 int out_len) = {
Alexander Chiang9afed762010-02-02 19:08:19 +000085 [IB_USER_VERBS_CMD_GET_CONTEXT] = ib_uverbs_get_context,
86 [IB_USER_VERBS_CMD_QUERY_DEVICE] = ib_uverbs_query_device,
87 [IB_USER_VERBS_CMD_QUERY_PORT] = ib_uverbs_query_port,
88 [IB_USER_VERBS_CMD_ALLOC_PD] = ib_uverbs_alloc_pd,
89 [IB_USER_VERBS_CMD_DEALLOC_PD] = ib_uverbs_dealloc_pd,
90 [IB_USER_VERBS_CMD_REG_MR] = ib_uverbs_reg_mr,
Matan Barak7e6edb92014-07-31 11:01:28 +030091 [IB_USER_VERBS_CMD_REREG_MR] = ib_uverbs_rereg_mr,
Alexander Chiang9afed762010-02-02 19:08:19 +000092 [IB_USER_VERBS_CMD_DEREG_MR] = ib_uverbs_dereg_mr,
Shani Michaeli6b52a122013-02-06 16:19:13 +000093 [IB_USER_VERBS_CMD_ALLOC_MW] = ib_uverbs_alloc_mw,
94 [IB_USER_VERBS_CMD_DEALLOC_MW] = ib_uverbs_dealloc_mw,
Roland Dreier6b73597e2005-09-26 13:53:25 -070095 [IB_USER_VERBS_CMD_CREATE_COMP_CHANNEL] = ib_uverbs_create_comp_channel,
Alexander Chiang9afed762010-02-02 19:08:19 +000096 [IB_USER_VERBS_CMD_CREATE_CQ] = ib_uverbs_create_cq,
97 [IB_USER_VERBS_CMD_RESIZE_CQ] = ib_uverbs_resize_cq,
98 [IB_USER_VERBS_CMD_POLL_CQ] = ib_uverbs_poll_cq,
99 [IB_USER_VERBS_CMD_REQ_NOTIFY_CQ] = ib_uverbs_req_notify_cq,
100 [IB_USER_VERBS_CMD_DESTROY_CQ] = ib_uverbs_destroy_cq,
101 [IB_USER_VERBS_CMD_CREATE_QP] = ib_uverbs_create_qp,
102 [IB_USER_VERBS_CMD_QUERY_QP] = ib_uverbs_query_qp,
103 [IB_USER_VERBS_CMD_MODIFY_QP] = ib_uverbs_modify_qp,
104 [IB_USER_VERBS_CMD_DESTROY_QP] = ib_uverbs_destroy_qp,
105 [IB_USER_VERBS_CMD_POST_SEND] = ib_uverbs_post_send,
106 [IB_USER_VERBS_CMD_POST_RECV] = ib_uverbs_post_recv,
107 [IB_USER_VERBS_CMD_POST_SRQ_RECV] = ib_uverbs_post_srq_recv,
108 [IB_USER_VERBS_CMD_CREATE_AH] = ib_uverbs_create_ah,
109 [IB_USER_VERBS_CMD_DESTROY_AH] = ib_uverbs_destroy_ah,
110 [IB_USER_VERBS_CMD_ATTACH_MCAST] = ib_uverbs_attach_mcast,
111 [IB_USER_VERBS_CMD_DETACH_MCAST] = ib_uverbs_detach_mcast,
112 [IB_USER_VERBS_CMD_CREATE_SRQ] = ib_uverbs_create_srq,
113 [IB_USER_VERBS_CMD_MODIFY_SRQ] = ib_uverbs_modify_srq,
114 [IB_USER_VERBS_CMD_QUERY_SRQ] = ib_uverbs_query_srq,
115 [IB_USER_VERBS_CMD_DESTROY_SRQ] = ib_uverbs_destroy_srq,
Sean Hefty53d0bd12011-05-24 08:33:46 -0700116 [IB_USER_VERBS_CMD_OPEN_XRCD] = ib_uverbs_open_xrcd,
117 [IB_USER_VERBS_CMD_CLOSE_XRCD] = ib_uverbs_close_xrcd,
Sean Hefty42849b22011-08-11 13:57:43 -0700118 [IB_USER_VERBS_CMD_CREATE_XSRQ] = ib_uverbs_create_xsrq,
Hadar Hen Zion436f2ad2013-08-14 13:58:30 +0300119 [IB_USER_VERBS_CMD_OPEN_QP] = ib_uverbs_open_qp,
Roland Dreierbc38a6a2005-07-07 17:57:13 -0700120};
121
Yann Droneaudf21519b2013-11-06 23:21:49 +0100122static int (*uverbs_ex_cmd_table[])(struct ib_uverbs_file *file,
Yishai Hadas057aec02015-08-13 18:32:04 +0300123 struct ib_device *ib_dev,
Yann Droneaudf21519b2013-11-06 23:21:49 +0100124 struct ib_udata *ucore,
125 struct ib_udata *uhw) = {
126 [IB_USER_VERBS_EX_CMD_CREATE_FLOW] = ib_uverbs_ex_create_flow,
Eli Cohen5a77abf2014-12-11 17:04:15 +0200127 [IB_USER_VERBS_EX_CMD_DESTROY_FLOW] = ib_uverbs_ex_destroy_flow,
Eli Cohen02d1aa72015-02-08 13:28:50 +0200128 [IB_USER_VERBS_EX_CMD_QUERY_DEVICE] = ib_uverbs_ex_query_device,
Matan Barak565197d2015-06-11 16:35:23 +0300129 [IB_USER_VERBS_EX_CMD_CREATE_CQ] = ib_uverbs_ex_create_cq,
Yann Droneaudf21519b2013-11-06 23:21:49 +0100130};
Yann Droneaudf21519b2013-11-06 23:21:49 +0100131
Roland Dreierbc38a6a2005-07-07 17:57:13 -0700132static void ib_uverbs_add_one(struct ib_device *device);
Haggai Eran7c1eb452015-07-30 17:50:14 +0300133static void ib_uverbs_remove_one(struct ib_device *device, void *client_data);
Roland Dreierbc38a6a2005-07-07 17:57:13 -0700134
Yishai Hadas35d4a0b2015-08-13 18:32:03 +0300135static void ib_uverbs_release_dev(struct kobject *kobj)
Roland Dreier70a30e12005-10-28 15:38:26 -0700136{
137 struct ib_uverbs_device *dev =
Yishai Hadas35d4a0b2015-08-13 18:32:03 +0300138 container_of(kobj, struct ib_uverbs_device, kobj);
Roland Dreier70a30e12005-10-28 15:38:26 -0700139
Yishai Hadas036b1062015-08-13 18:32:05 +0300140 cleanup_srcu_struct(&dev->disassociate_srcu);
Yishai Hadas35d4a0b2015-08-13 18:32:03 +0300141 kfree(dev);
Roland Dreier70a30e12005-10-28 15:38:26 -0700142}
143
Yishai Hadas35d4a0b2015-08-13 18:32:03 +0300144static struct kobj_type ib_uverbs_dev_ktype = {
145 .release = ib_uverbs_release_dev,
146};
147
Roland Dreier04d29b02007-10-09 19:59:15 -0700148static void ib_uverbs_release_event_file(struct kref *ref)
149{
150 struct ib_uverbs_event_file *file =
151 container_of(ref, struct ib_uverbs_event_file, ref);
152
153 kfree(file);
154}
155
Roland Dreier70a30e12005-10-28 15:38:26 -0700156void ib_uverbs_release_ucq(struct ib_uverbs_file *file,
157 struct ib_uverbs_event_file *ev_file,
158 struct ib_ucq_object *uobj)
159{
160 struct ib_uverbs_event *evt, *tmp;
161
162 if (ev_file) {
163 spin_lock_irq(&ev_file->lock);
164 list_for_each_entry_safe(evt, tmp, &uobj->comp_list, obj_list) {
165 list_del(&evt->list);
166 kfree(evt);
167 }
168 spin_unlock_irq(&ev_file->lock);
169
170 kref_put(&ev_file->ref, ib_uverbs_release_event_file);
171 }
172
173 spin_lock_irq(&file->async_file->lock);
174 list_for_each_entry_safe(evt, tmp, &uobj->async_list, obj_list) {
175 list_del(&evt->list);
176 kfree(evt);
177 }
178 spin_unlock_irq(&file->async_file->lock);
179}
180
181void ib_uverbs_release_uevent(struct ib_uverbs_file *file,
182 struct ib_uevent_object *uobj)
183{
184 struct ib_uverbs_event *evt, *tmp;
185
186 spin_lock_irq(&file->async_file->lock);
187 list_for_each_entry_safe(evt, tmp, &uobj->event_list, obj_list) {
188 list_del(&evt->list);
189 kfree(evt);
190 }
191 spin_unlock_irq(&file->async_file->lock);
192}
193
Jack Morgensteinf4e40152005-11-29 16:57:01 -0800194static void ib_uverbs_detach_umcast(struct ib_qp *qp,
195 struct ib_uqp_object *uobj)
196{
197 struct ib_uverbs_mcast_entry *mcast, *tmp;
198
199 list_for_each_entry_safe(mcast, tmp, &uobj->mcast_list, list) {
200 ib_detach_mcast(qp, &mcast->gid, mcast->lid);
201 list_del(&mcast->list);
202 kfree(mcast);
203 }
204}
205
Roland Dreier70a30e12005-10-28 15:38:26 -0700206static int ib_uverbs_cleanup_ucontext(struct ib_uverbs_file *file,
207 struct ib_ucontext *context)
Roland Dreierbc38a6a2005-07-07 17:57:13 -0700208{
209 struct ib_uobject *uobj, *tmp;
210
Roland Dreierf7c6a7b2007-03-04 16:15:11 -0800211 context->closing = 1;
212
Roland Dreier67cdb402005-10-14 15:26:04 -0700213 list_for_each_entry_safe(uobj, tmp, &context->ah_list, list) {
Roland Dreier9ead1902006-06-17 20:44:49 -0700214 struct ib_ah *ah = uobj->object;
215
216 idr_remove_uobj(&ib_uverbs_ah_idr, uobj);
Roland Dreier67cdb402005-10-14 15:26:04 -0700217 ib_destroy_ah(ah);
Roland Dreier67cdb402005-10-14 15:26:04 -0700218 kfree(uobj);
219 }
Roland Dreierbc38a6a2005-07-07 17:57:13 -0700220
Shani Michaeli6b52a122013-02-06 16:19:13 +0000221 /* Remove MWs before QPs, in order to support type 2A MWs. */
222 list_for_each_entry_safe(uobj, tmp, &context->mw_list, list) {
223 struct ib_mw *mw = uobj->object;
224
225 idr_remove_uobj(&ib_uverbs_mw_idr, uobj);
226 ib_dealloc_mw(mw);
227 kfree(uobj);
228 }
229
Hadar Hen Zion436f2ad2013-08-14 13:58:30 +0300230 list_for_each_entry_safe(uobj, tmp, &context->rule_list, list) {
231 struct ib_flow *flow_id = uobj->object;
232
233 idr_remove_uobj(&ib_uverbs_rule_idr, uobj);
234 ib_destroy_flow(flow_id);
235 kfree(uobj);
236 }
237
Roland Dreierbc38a6a2005-07-07 17:57:13 -0700238 list_for_each_entry_safe(uobj, tmp, &context->qp_list, list) {
Roland Dreier9ead1902006-06-17 20:44:49 -0700239 struct ib_qp *qp = uobj->object;
Jack Morgensteinf4e40152005-11-29 16:57:01 -0800240 struct ib_uqp_object *uqp =
241 container_of(uobj, struct ib_uqp_object, uevent.uobject);
Roland Dreier9ead1902006-06-17 20:44:49 -0700242
243 idr_remove_uobj(&ib_uverbs_qp_idr, uobj);
Sean Hefty0e0ec7e2011-08-08 15:31:51 -0700244 if (qp != qp->real_qp) {
245 ib_close_qp(qp);
Sean Heftyb93f3c12011-05-27 00:00:12 -0700246 } else {
247 ib_uverbs_detach_umcast(qp, uqp);
248 ib_destroy_qp(qp);
249 }
Jack Morgensteinf4e40152005-11-29 16:57:01 -0800250 ib_uverbs_release_uevent(file, &uqp->uevent);
251 kfree(uqp);
Roland Dreierbc38a6a2005-07-07 17:57:13 -0700252 }
253
Sébastien Duguéa233c4b2015-04-09 11:13:41 +0200254 list_for_each_entry_safe(uobj, tmp, &context->srq_list, list) {
255 struct ib_srq *srq = uobj->object;
256 struct ib_uevent_object *uevent =
257 container_of(uobj, struct ib_uevent_object, uobject);
258
259 idr_remove_uobj(&ib_uverbs_srq_idr, uobj);
260 ib_destroy_srq(srq);
261 ib_uverbs_release_uevent(file, uevent);
262 kfree(uevent);
263 }
264
Roland Dreierbc38a6a2005-07-07 17:57:13 -0700265 list_for_each_entry_safe(uobj, tmp, &context->cq_list, list) {
Roland Dreier9ead1902006-06-17 20:44:49 -0700266 struct ib_cq *cq = uobj->object;
Roland Dreier70a30e12005-10-28 15:38:26 -0700267 struct ib_uverbs_event_file *ev_file = cq->cq_context;
268 struct ib_ucq_object *ucq =
269 container_of(uobj, struct ib_ucq_object, uobject);
Roland Dreier9ead1902006-06-17 20:44:49 -0700270
271 idr_remove_uobj(&ib_uverbs_cq_idr, uobj);
Roland Dreierbc38a6a2005-07-07 17:57:13 -0700272 ib_destroy_cq(cq);
Roland Dreier70a30e12005-10-28 15:38:26 -0700273 ib_uverbs_release_ucq(file, ev_file, ucq);
274 kfree(ucq);
Roland Dreierbc38a6a2005-07-07 17:57:13 -0700275 }
276
Roland Dreierbc38a6a2005-07-07 17:57:13 -0700277 list_for_each_entry_safe(uobj, tmp, &context->mr_list, list) {
Roland Dreier9ead1902006-06-17 20:44:49 -0700278 struct ib_mr *mr = uobj->object;
Roland Dreierbc38a6a2005-07-07 17:57:13 -0700279
Roland Dreier9ead1902006-06-17 20:44:49 -0700280 idr_remove_uobj(&ib_uverbs_mr_idr, uobj);
Roland Dreierbc38a6a2005-07-07 17:57:13 -0700281 ib_dereg_mr(mr);
Roland Dreierf7c6a7b2007-03-04 16:15:11 -0800282 kfree(uobj);
Roland Dreierbc38a6a2005-07-07 17:57:13 -0700283 }
284
Sean Hefty53d0bd12011-05-24 08:33:46 -0700285 mutex_lock(&file->device->xrcd_tree_mutex);
286 list_for_each_entry_safe(uobj, tmp, &context->xrcd_list, list) {
287 struct ib_xrcd *xrcd = uobj->object;
288 struct ib_uxrcd_object *uxrcd =
289 container_of(uobj, struct ib_uxrcd_object, uobject);
290
291 idr_remove_uobj(&ib_uverbs_xrcd_idr, uobj);
292 ib_uverbs_dealloc_xrcd(file->device, xrcd);
293 kfree(uxrcd);
294 }
295 mutex_unlock(&file->device->xrcd_tree_mutex);
296
Roland Dreierbc38a6a2005-07-07 17:57:13 -0700297 list_for_each_entry_safe(uobj, tmp, &context->pd_list, list) {
Roland Dreier9ead1902006-06-17 20:44:49 -0700298 struct ib_pd *pd = uobj->object;
299
300 idr_remove_uobj(&ib_uverbs_pd_idr, uobj);
Roland Dreierbc38a6a2005-07-07 17:57:13 -0700301 ib_dealloc_pd(pd);
Roland Dreierbc38a6a2005-07-07 17:57:13 -0700302 kfree(uobj);
303 }
304
Shachar Raindel8ada2c12014-12-11 17:04:17 +0200305 put_pid(context->tgid);
306
Roland Dreierbc38a6a2005-07-07 17:57:13 -0700307 return context->device->dealloc_ucontext(context);
308}
309
Yishai Hadas35d4a0b2015-08-13 18:32:03 +0300310static void ib_uverbs_comp_dev(struct ib_uverbs_device *dev)
311{
312 complete(&dev->comp);
313}
314
Roland Dreierbc38a6a2005-07-07 17:57:13 -0700315static void ib_uverbs_release_file(struct kref *ref)
316{
317 struct ib_uverbs_file *file =
318 container_of(ref, struct ib_uverbs_file, ref);
Yishai Hadas036b1062015-08-13 18:32:05 +0300319 struct ib_device *ib_dev;
320 int srcu_key;
Roland Dreierbc38a6a2005-07-07 17:57:13 -0700321
Yishai Hadas036b1062015-08-13 18:32:05 +0300322 srcu_key = srcu_read_lock(&file->device->disassociate_srcu);
323 ib_dev = srcu_dereference(file->device->ib_dev,
324 &file->device->disassociate_srcu);
325 if (ib_dev && !ib_dev->disassociate_ucontext)
326 module_put(ib_dev->owner);
327 srcu_read_unlock(&file->device->disassociate_srcu, srcu_key);
328
Yishai Hadas35d4a0b2015-08-13 18:32:03 +0300329 if (atomic_dec_and_test(&file->device->refcount))
330 ib_uverbs_comp_dev(file->device);
Roland Dreier70a30e12005-10-28 15:38:26 -0700331
Roland Dreierbc38a6a2005-07-07 17:57:13 -0700332 kfree(file);
333}
334
335static ssize_t ib_uverbs_event_read(struct file *filp, char __user *buf,
336 size_t count, loff_t *pos)
337{
338 struct ib_uverbs_event_file *file = filp->private_data;
Roland Dreier63aaf642005-09-09 15:55:08 -0700339 struct ib_uverbs_event *event;
Roland Dreierbc38a6a2005-07-07 17:57:13 -0700340 int eventsz;
341 int ret = 0;
342
343 spin_lock_irq(&file->lock);
344
Roland Dreier6b73597e2005-09-26 13:53:25 -0700345 while (list_empty(&file->event_list)) {
Roland Dreierbc38a6a2005-07-07 17:57:13 -0700346 spin_unlock_irq(&file->lock);
347
348 if (filp->f_flags & O_NONBLOCK)
349 return -EAGAIN;
350
351 if (wait_event_interruptible(file->poll_wait,
Yishai Hadas036b1062015-08-13 18:32:05 +0300352 (!list_empty(&file->event_list) ||
353 /* The barriers built into wait_event_interruptible()
354 * and wake_up() guarentee this will see the null set
355 * without using RCU
356 */
357 !file->uverbs_file->device->ib_dev)))
Roland Dreierbc38a6a2005-07-07 17:57:13 -0700358 return -ERESTARTSYS;
359
Yishai Hadas036b1062015-08-13 18:32:05 +0300360 /* If device was disassociated and no event exists set an error */
361 if (list_empty(&file->event_list) &&
362 !file->uverbs_file->device->ib_dev)
363 return -EIO;
364
Roland Dreierbc38a6a2005-07-07 17:57:13 -0700365 spin_lock_irq(&file->lock);
366 }
367
Roland Dreier63aaf642005-09-09 15:55:08 -0700368 event = list_entry(file->event_list.next, struct ib_uverbs_event, list);
369
370 if (file->is_async)
Roland Dreierbc38a6a2005-07-07 17:57:13 -0700371 eventsz = sizeof (struct ib_uverbs_async_event_desc);
Roland Dreier63aaf642005-09-09 15:55:08 -0700372 else
Roland Dreierbc38a6a2005-07-07 17:57:13 -0700373 eventsz = sizeof (struct ib_uverbs_comp_event_desc);
Roland Dreierbc38a6a2005-07-07 17:57:13 -0700374
375 if (eventsz > count) {
376 ret = -EINVAL;
377 event = NULL;
Roland Dreier63aaf642005-09-09 15:55:08 -0700378 } else {
Roland Dreierbc38a6a2005-07-07 17:57:13 -0700379 list_del(file->event_list.next);
Roland Dreier63aaf642005-09-09 15:55:08 -0700380 if (event->counter) {
381 ++(*event->counter);
382 list_del(&event->obj_list);
383 }
384 }
Roland Dreierbc38a6a2005-07-07 17:57:13 -0700385
386 spin_unlock_irq(&file->lock);
387
388 if (event) {
389 if (copy_to_user(buf, event, eventsz))
390 ret = -EFAULT;
391 else
392 ret = eventsz;
393 }
394
395 kfree(event);
396
397 return ret;
398}
399
400static unsigned int ib_uverbs_event_poll(struct file *filp,
401 struct poll_table_struct *wait)
402{
403 unsigned int pollflags = 0;
404 struct ib_uverbs_event_file *file = filp->private_data;
405
406 poll_wait(filp, &file->poll_wait, wait);
407
408 spin_lock_irq(&file->lock);
Roland Dreier6b73597e2005-09-26 13:53:25 -0700409 if (!list_empty(&file->event_list))
Roland Dreierbc38a6a2005-07-07 17:57:13 -0700410 pollflags = POLLIN | POLLRDNORM;
411 spin_unlock_irq(&file->lock);
412
413 return pollflags;
414}
415
Gleb Natapovabdf1192005-07-27 14:40:00 -0700416static int ib_uverbs_event_fasync(int fd, struct file *filp, int on)
417{
418 struct ib_uverbs_event_file *file = filp->private_data;
419
420 return fasync_helper(fd, filp, on, &file->async_queue);
421}
422
Roland Dreierbc38a6a2005-07-07 17:57:13 -0700423static int ib_uverbs_event_close(struct inode *inode, struct file *filp)
424{
425 struct ib_uverbs_event_file *file = filp->private_data;
Roland Dreier6b73597e2005-09-26 13:53:25 -0700426 struct ib_uverbs_event *entry, *tmp;
Yishai Hadas036b1062015-08-13 18:32:05 +0300427 int closed_already = 0;
Roland Dreierbc38a6a2005-07-07 17:57:13 -0700428
Yishai Hadas036b1062015-08-13 18:32:05 +0300429 mutex_lock(&file->uverbs_file->device->lists_mutex);
Roland Dreier6b73597e2005-09-26 13:53:25 -0700430 spin_lock_irq(&file->lock);
Yishai Hadas036b1062015-08-13 18:32:05 +0300431 closed_already = file->is_closed;
Roland Dreier1ae5c182008-04-16 21:01:08 -0700432 file->is_closed = 1;
Roland Dreier6b73597e2005-09-26 13:53:25 -0700433 list_for_each_entry_safe(entry, tmp, &file->event_list, list) {
434 if (entry->counter)
435 list_del(&entry->obj_list);
436 kfree(entry);
437 }
438 spin_unlock_irq(&file->lock);
Yishai Hadas036b1062015-08-13 18:32:05 +0300439 if (!closed_already) {
440 list_del(&file->list);
441 if (file->is_async)
442 ib_unregister_event_handler(&file->uverbs_file->
443 event_handler);
444 }
445 mutex_unlock(&file->uverbs_file->device->lists_mutex);
Roland Dreier6b73597e2005-09-26 13:53:25 -0700446
Yishai Hadas03c40442015-08-13 18:32:02 +0300447 kref_put(&file->uverbs_file->ref, ib_uverbs_release_file);
Roland Dreier6b73597e2005-09-26 13:53:25 -0700448 kref_put(&file->ref, ib_uverbs_release_event_file);
Roland Dreierbc38a6a2005-07-07 17:57:13 -0700449
450 return 0;
451}
452
Arjan van de Ven2b8693c2007-02-12 00:55:32 -0800453static const struct file_operations uverbs_event_fops = {
Roland Dreier6b73597e2005-09-26 13:53:25 -0700454 .owner = THIS_MODULE,
Alexander Chiang9afed762010-02-02 19:08:19 +0000455 .read = ib_uverbs_event_read,
Roland Dreierbc38a6a2005-07-07 17:57:13 -0700456 .poll = ib_uverbs_event_poll,
Gleb Natapovabdf1192005-07-27 14:40:00 -0700457 .release = ib_uverbs_event_close,
Roland Dreierbc1db9a2010-04-09 17:13:50 -0700458 .fasync = ib_uverbs_event_fasync,
459 .llseek = no_llseek,
Roland Dreierbc38a6a2005-07-07 17:57:13 -0700460};
461
462void ib_uverbs_comp_handler(struct ib_cq *cq, void *cq_context)
463{
Roland Dreier6b73597e2005-09-26 13:53:25 -0700464 struct ib_uverbs_event_file *file = cq_context;
465 struct ib_ucq_object *uobj;
466 struct ib_uverbs_event *entry;
467 unsigned long flags;
468
469 if (!file)
470 return;
471
472 spin_lock_irqsave(&file->lock, flags);
Roland Dreier1ae5c182008-04-16 21:01:08 -0700473 if (file->is_closed) {
Roland Dreier6b73597e2005-09-26 13:53:25 -0700474 spin_unlock_irqrestore(&file->lock, flags);
475 return;
476 }
Roland Dreierbc38a6a2005-07-07 17:57:13 -0700477
478 entry = kmalloc(sizeof *entry, GFP_ATOMIC);
Roland Dreier305a7e82005-10-11 15:39:38 -0700479 if (!entry) {
480 spin_unlock_irqrestore(&file->lock, flags);
Roland Dreierbc38a6a2005-07-07 17:57:13 -0700481 return;
Roland Dreier305a7e82005-10-11 15:39:38 -0700482 }
Roland Dreierbc38a6a2005-07-07 17:57:13 -0700483
Roland Dreier63aaf642005-09-09 15:55:08 -0700484 uobj = container_of(cq->uobject, struct ib_ucq_object, uobject);
485
486 entry->desc.comp.cq_handle = cq->uobject->user_handle;
487 entry->counter = &uobj->comp_events_reported;
Roland Dreierbc38a6a2005-07-07 17:57:13 -0700488
Roland Dreier6b73597e2005-09-26 13:53:25 -0700489 list_add_tail(&entry->list, &file->event_list);
Roland Dreier63aaf642005-09-09 15:55:08 -0700490 list_add_tail(&entry->obj_list, &uobj->comp_list);
Roland Dreier6b73597e2005-09-26 13:53:25 -0700491 spin_unlock_irqrestore(&file->lock, flags);
Roland Dreierbc38a6a2005-07-07 17:57:13 -0700492
Roland Dreier6b73597e2005-09-26 13:53:25 -0700493 wake_up_interruptible(&file->poll_wait);
494 kill_fasync(&file->async_queue, SIGIO, POLL_IN);
Roland Dreierbc38a6a2005-07-07 17:57:13 -0700495}
496
497static void ib_uverbs_async_handler(struct ib_uverbs_file *file,
Roland Dreier63aaf642005-09-09 15:55:08 -0700498 __u64 element, __u64 event,
499 struct list_head *obj_list,
500 u32 *counter)
Roland Dreierbc38a6a2005-07-07 17:57:13 -0700501{
Roland Dreier63aaf642005-09-09 15:55:08 -0700502 struct ib_uverbs_event *entry;
Roland Dreierbc38a6a2005-07-07 17:57:13 -0700503 unsigned long flags;
504
Roland Dreier6b73597e2005-09-26 13:53:25 -0700505 spin_lock_irqsave(&file->async_file->lock, flags);
Jack Morgensteinfb77bce2008-06-18 15:36:38 -0700506 if (file->async_file->is_closed) {
Roland Dreier6b73597e2005-09-26 13:53:25 -0700507 spin_unlock_irqrestore(&file->async_file->lock, flags);
508 return;
509 }
510
Roland Dreierbc38a6a2005-07-07 17:57:13 -0700511 entry = kmalloc(sizeof *entry, GFP_ATOMIC);
Roland Dreier305a7e82005-10-11 15:39:38 -0700512 if (!entry) {
513 spin_unlock_irqrestore(&file->async_file->lock, flags);
Roland Dreierbc38a6a2005-07-07 17:57:13 -0700514 return;
Roland Dreier305a7e82005-10-11 15:39:38 -0700515 }
Roland Dreierbc38a6a2005-07-07 17:57:13 -0700516
Roland Dreier63aaf642005-09-09 15:55:08 -0700517 entry->desc.async.element = element;
518 entry->desc.async.event_type = event;
Eli Cohen377b5132014-09-14 16:47:52 +0300519 entry->desc.async.reserved = 0;
Roland Dreier63aaf642005-09-09 15:55:08 -0700520 entry->counter = counter;
Roland Dreierbc38a6a2005-07-07 17:57:13 -0700521
Roland Dreier6b73597e2005-09-26 13:53:25 -0700522 list_add_tail(&entry->list, &file->async_file->event_list);
Roland Dreier63aaf642005-09-09 15:55:08 -0700523 if (obj_list)
524 list_add_tail(&entry->obj_list, obj_list);
Roland Dreier6b73597e2005-09-26 13:53:25 -0700525 spin_unlock_irqrestore(&file->async_file->lock, flags);
Roland Dreierbc38a6a2005-07-07 17:57:13 -0700526
Roland Dreier6b73597e2005-09-26 13:53:25 -0700527 wake_up_interruptible(&file->async_file->poll_wait);
528 kill_fasync(&file->async_file->async_queue, SIGIO, POLL_IN);
Roland Dreierbc38a6a2005-07-07 17:57:13 -0700529}
530
531void ib_uverbs_cq_event_handler(struct ib_event *event, void *context_ptr)
532{
Roland Dreier7162a3e2005-10-30 09:50:04 -0800533 struct ib_ucq_object *uobj = container_of(event->element.cq->uobject,
534 struct ib_ucq_object, uobject);
Roland Dreier63aaf642005-09-09 15:55:08 -0700535
Roland Dreier7162a3e2005-10-30 09:50:04 -0800536 ib_uverbs_async_handler(uobj->uverbs_file, uobj->uobject.user_handle,
Roland Dreier63aaf642005-09-09 15:55:08 -0700537 event->event, &uobj->async_list,
538 &uobj->async_events_reported);
Roland Dreierbc38a6a2005-07-07 17:57:13 -0700539}
540
541void ib_uverbs_qp_event_handler(struct ib_event *event, void *context_ptr)
542{
Roland Dreier63aaf642005-09-09 15:55:08 -0700543 struct ib_uevent_object *uobj;
544
Jack Morgensteina040f952014-09-23 12:38:26 +0300545 /* for XRC target qp's, check that qp is live */
546 if (!event->element.qp->uobject || !event->element.qp->uobject->live)
547 return;
548
Roland Dreier63aaf642005-09-09 15:55:08 -0700549 uobj = container_of(event->element.qp->uobject,
550 struct ib_uevent_object, uobject);
551
552 ib_uverbs_async_handler(context_ptr, uobj->uobject.user_handle,
553 event->event, &uobj->event_list,
554 &uobj->events_reported);
Roland Dreierbc38a6a2005-07-07 17:57:13 -0700555}
556
Roland Dreierf520ba52005-08-18 12:24:13 -0700557void ib_uverbs_srq_event_handler(struct ib_event *event, void *context_ptr)
558{
Roland Dreier63aaf642005-09-09 15:55:08 -0700559 struct ib_uevent_object *uobj;
560
561 uobj = container_of(event->element.srq->uobject,
562 struct ib_uevent_object, uobject);
563
564 ib_uverbs_async_handler(context_ptr, uobj->uobject.user_handle,
565 event->event, &uobj->event_list,
566 &uobj->events_reported);
Roland Dreierf520ba52005-08-18 12:24:13 -0700567}
568
Roland Dreier6b73597e2005-09-26 13:53:25 -0700569void ib_uverbs_event_handler(struct ib_event_handler *handler,
570 struct ib_event *event)
Roland Dreierbc38a6a2005-07-07 17:57:13 -0700571{
572 struct ib_uverbs_file *file =
573 container_of(handler, struct ib_uverbs_file, event_handler);
574
Roland Dreier63aaf642005-09-09 15:55:08 -0700575 ib_uverbs_async_handler(file, event->element.port_num, event->event,
576 NULL, NULL);
Roland Dreierbc38a6a2005-07-07 17:57:13 -0700577}
578
Yishai Hadas03c40442015-08-13 18:32:02 +0300579void ib_uverbs_free_async_event_file(struct ib_uverbs_file *file)
580{
581 kref_put(&file->async_file->ref, ib_uverbs_release_event_file);
582 file->async_file = NULL;
583}
584
Roland Dreier6b73597e2005-09-26 13:53:25 -0700585struct file *ib_uverbs_alloc_event_file(struct ib_uverbs_file *uverbs_file,
Yishai Hadas057aec02015-08-13 18:32:04 +0300586 struct ib_device *ib_dev,
Al Virob1e4594b2010-01-18 01:38:00 -0500587 int is_async)
Roland Dreierbc38a6a2005-07-07 17:57:13 -0700588{
Roland Dreier6b73597e2005-09-26 13:53:25 -0700589 struct ib_uverbs_event_file *ev_file;
Roland Dreierbc38a6a2005-07-07 17:57:13 -0700590 struct file *filp;
Yishai Hadas03c40442015-08-13 18:32:02 +0300591 int ret;
Roland Dreierbc38a6a2005-07-07 17:57:13 -0700592
Yishai Hadas03c40442015-08-13 18:32:02 +0300593 ev_file = kzalloc(sizeof(*ev_file), GFP_KERNEL);
Roland Dreier6b73597e2005-09-26 13:53:25 -0700594 if (!ev_file)
595 return ERR_PTR(-ENOMEM);
Roland Dreierbc38a6a2005-07-07 17:57:13 -0700596
Roland Dreier6b73597e2005-09-26 13:53:25 -0700597 kref_init(&ev_file->ref);
598 spin_lock_init(&ev_file->lock);
599 INIT_LIST_HEAD(&ev_file->event_list);
600 init_waitqueue_head(&ev_file->poll_wait);
601 ev_file->uverbs_file = uverbs_file;
Yishai Hadas03c40442015-08-13 18:32:02 +0300602 kref_get(&ev_file->uverbs_file->ref);
Roland Dreier6b73597e2005-09-26 13:53:25 -0700603 ev_file->async_queue = NULL;
Roland Dreier1ae5c182008-04-16 21:01:08 -0700604 ev_file->is_closed = 0;
Roland Dreier6b73597e2005-09-26 13:53:25 -0700605
Al Virob1e4594b2010-01-18 01:38:00 -0500606 filp = anon_inode_getfile("[infinibandevent]", &uverbs_event_fops,
Roland Dreiera265e552010-02-24 16:51:20 -0800607 ev_file, O_RDONLY);
Al Virob1e4594b2010-01-18 01:38:00 -0500608 if (IS_ERR(filp))
Yishai Hadas03c40442015-08-13 18:32:02 +0300609 goto err_put_refs;
Roland Dreiera7dab9e2008-04-16 21:01:08 -0700610
Yishai Hadas036b1062015-08-13 18:32:05 +0300611 mutex_lock(&uverbs_file->device->lists_mutex);
612 list_add_tail(&ev_file->list,
613 &uverbs_file->device->uverbs_events_file_list);
614 mutex_unlock(&uverbs_file->device->lists_mutex);
615
Yishai Hadas03c40442015-08-13 18:32:02 +0300616 if (is_async) {
617 WARN_ON(uverbs_file->async_file);
618 uverbs_file->async_file = ev_file;
619 kref_get(&uverbs_file->async_file->ref);
620 INIT_IB_EVENT_HANDLER(&uverbs_file->event_handler,
Yishai Hadas057aec02015-08-13 18:32:04 +0300621 ib_dev,
Yishai Hadas03c40442015-08-13 18:32:02 +0300622 ib_uverbs_event_handler);
623 ret = ib_register_event_handler(&uverbs_file->event_handler);
624 if (ret)
625 goto err_put_file;
626
627 /* At that point async file stuff was fully set */
628 ev_file->is_async = 1;
629 }
630
631 return filp;
632
633err_put_file:
634 fput(filp);
635 kref_put(&uverbs_file->async_file->ref, ib_uverbs_release_event_file);
636 uverbs_file->async_file = NULL;
637 return ERR_PTR(ret);
638
639err_put_refs:
640 kref_put(&ev_file->uverbs_file->ref, ib_uverbs_release_file);
641 kref_put(&ev_file->ref, ib_uverbs_release_event_file);
Roland Dreier6b73597e2005-09-26 13:53:25 -0700642 return filp;
Roland Dreier6b73597e2005-09-26 13:53:25 -0700643}
644
645/*
646 * Look up a completion event file by FD. If lookup is successful,
647 * takes a ref to the event file struct that it returns; if
648 * unsuccessful, returns NULL.
649 */
650struct ib_uverbs_event_file *ib_uverbs_lookup_comp_file(int fd)
651{
652 struct ib_uverbs_event_file *ev_file = NULL;
Al Viro2903ff02012-08-28 12:52:22 -0400653 struct fd f = fdget(fd);
Roland Dreier6b73597e2005-09-26 13:53:25 -0700654
Al Viro2903ff02012-08-28 12:52:22 -0400655 if (!f.file)
Roland Dreier6b73597e2005-09-26 13:53:25 -0700656 return NULL;
657
Al Viro2903ff02012-08-28 12:52:22 -0400658 if (f.file->f_op != &uverbs_event_fops)
Roland Dreier6b73597e2005-09-26 13:53:25 -0700659 goto out;
660
Al Viro2903ff02012-08-28 12:52:22 -0400661 ev_file = f.file->private_data;
Roland Dreier6b73597e2005-09-26 13:53:25 -0700662 if (ev_file->is_async) {
663 ev_file = NULL;
664 goto out;
665 }
666
667 kref_get(&ev_file->ref);
668
669out:
Al Viro2903ff02012-08-28 12:52:22 -0400670 fdput(f);
Roland Dreier6b73597e2005-09-26 13:53:25 -0700671 return ev_file;
Roland Dreierbc38a6a2005-07-07 17:57:13 -0700672}
673
674static ssize_t ib_uverbs_write(struct file *filp, const char __user *buf,
675 size_t count, loff_t *pos)
676{
677 struct ib_uverbs_file *file = filp->private_data;
Yishai Hadas036b1062015-08-13 18:32:05 +0300678 struct ib_device *ib_dev;
Roland Dreierbc38a6a2005-07-07 17:57:13 -0700679 struct ib_uverbs_cmd_hdr hdr;
Yann Droneaudf21519b2013-11-06 23:21:49 +0100680 __u32 flags;
Yishai Hadas036b1062015-08-13 18:32:05 +0300681 int srcu_key;
682 ssize_t ret;
Yishai Hadas057aec02015-08-13 18:32:04 +0300683
Roland Dreierbc38a6a2005-07-07 17:57:13 -0700684 if (count < sizeof hdr)
685 return -EINVAL;
686
687 if (copy_from_user(&hdr, buf, sizeof hdr))
688 return -EFAULT;
689
Yishai Hadas036b1062015-08-13 18:32:05 +0300690 srcu_key = srcu_read_lock(&file->device->disassociate_srcu);
691 ib_dev = srcu_dereference(file->device->ib_dev,
692 &file->device->disassociate_srcu);
693 if (!ib_dev) {
694 ret = -EIO;
695 goto out;
696 }
697
Yann Droneaudf21519b2013-11-06 23:21:49 +0100698 flags = (hdr.command &
699 IB_USER_VERBS_CMD_FLAGS_MASK) >> IB_USER_VERBS_CMD_FLAGS_SHIFT;
Roland Dreierbc38a6a2005-07-07 17:57:13 -0700700
Yann Droneaudf21519b2013-11-06 23:21:49 +0100701 if (!flags) {
702 __u32 command;
Roland Dreierbc38a6a2005-07-07 17:57:13 -0700703
Yann Droneaudf21519b2013-11-06 23:21:49 +0100704 if (hdr.command & ~(__u32)(IB_USER_VERBS_CMD_FLAGS_MASK |
Yishai Hadas036b1062015-08-13 18:32:05 +0300705 IB_USER_VERBS_CMD_COMMAND_MASK)) {
706 ret = -EINVAL;
707 goto out;
708 }
Igor Ivanov400dbc92013-08-14 13:58:29 +0300709
Yann Droneaudf21519b2013-11-06 23:21:49 +0100710 command = hdr.command & IB_USER_VERBS_CMD_COMMAND_MASK;
711
712 if (command >= ARRAY_SIZE(uverbs_cmd_table) ||
Yishai Hadas036b1062015-08-13 18:32:05 +0300713 !uverbs_cmd_table[command]) {
714 ret = -EINVAL;
715 goto out;
716 }
Yann Droneaudf21519b2013-11-06 23:21:49 +0100717
718 if (!file->ucontext &&
Yishai Hadas036b1062015-08-13 18:32:05 +0300719 command != IB_USER_VERBS_CMD_GET_CONTEXT) {
720 ret = -EINVAL;
721 goto out;
722 }
Yann Droneaudf21519b2013-11-06 23:21:49 +0100723
Yishai Hadas036b1062015-08-13 18:32:05 +0300724 if (!(ib_dev->uverbs_cmd_mask & (1ull << command))) {
725 ret = -ENOSYS;
726 goto out;
727 }
Yann Droneaudf21519b2013-11-06 23:21:49 +0100728
Yishai Hadas036b1062015-08-13 18:32:05 +0300729 if (hdr.in_words * 4 != count) {
730 ret = -EINVAL;
731 goto out;
732 }
Igor Ivanov400dbc92013-08-14 13:58:29 +0300733
Yishai Hadas036b1062015-08-13 18:32:05 +0300734 ret = uverbs_cmd_table[command](file, ib_dev,
Yann Droneaudf21519b2013-11-06 23:21:49 +0100735 buf + sizeof(hdr),
736 hdr.in_words * 4,
737 hdr.out_words * 4);
738
Yann Droneaudf21519b2013-11-06 23:21:49 +0100739 } else if (flags == IB_USER_VERBS_CMD_FLAG_EXTENDED) {
740 __u32 command;
741
742 struct ib_uverbs_ex_cmd_hdr ex_hdr;
743 struct ib_udata ucore;
744 struct ib_udata uhw;
Yann Droneaudf21519b2013-11-06 23:21:49 +0100745 size_t written_count = count;
746
747 if (hdr.command & ~(__u32)(IB_USER_VERBS_CMD_FLAGS_MASK |
Yishai Hadas036b1062015-08-13 18:32:05 +0300748 IB_USER_VERBS_CMD_COMMAND_MASK)) {
749 ret = -EINVAL;
750 goto out;
751 }
Yann Droneaudf21519b2013-11-06 23:21:49 +0100752
753 command = hdr.command & IB_USER_VERBS_CMD_COMMAND_MASK;
754
755 if (command >= ARRAY_SIZE(uverbs_ex_cmd_table) ||
Yishai Hadas036b1062015-08-13 18:32:05 +0300756 !uverbs_ex_cmd_table[command]) {
757 ret = -ENOSYS;
758 goto out;
759 }
Yann Droneaudf21519b2013-11-06 23:21:49 +0100760
Yishai Hadas036b1062015-08-13 18:32:05 +0300761 if (!file->ucontext) {
762 ret = -EINVAL;
763 goto out;
764 }
Yann Droneaudf21519b2013-11-06 23:21:49 +0100765
Yishai Hadas036b1062015-08-13 18:32:05 +0300766 if (!(ib_dev->uverbs_ex_cmd_mask & (1ull << command))) {
767 ret = -ENOSYS;
768 goto out;
769 }
Yann Droneaudf21519b2013-11-06 23:21:49 +0100770
Yishai Hadas036b1062015-08-13 18:32:05 +0300771 if (count < (sizeof(hdr) + sizeof(ex_hdr))) {
772 ret = -EINVAL;
773 goto out;
774 }
Yann Droneaudf21519b2013-11-06 23:21:49 +0100775
Yishai Hadas036b1062015-08-13 18:32:05 +0300776 if (copy_from_user(&ex_hdr, buf + sizeof(hdr), sizeof(ex_hdr))) {
777 ret = -EFAULT;
778 goto out;
779 }
Yann Droneaudf21519b2013-11-06 23:21:49 +0100780
781 count -= sizeof(hdr) + sizeof(ex_hdr);
782 buf += sizeof(hdr) + sizeof(ex_hdr);
783
Yishai Hadas036b1062015-08-13 18:32:05 +0300784 if ((hdr.in_words + ex_hdr.provider_in_words) * 8 != count) {
785 ret = -EINVAL;
786 goto out;
787 }
Yann Droneaudf21519b2013-11-06 23:21:49 +0100788
Yishai Hadas036b1062015-08-13 18:32:05 +0300789 if (ex_hdr.cmd_hdr_reserved) {
790 ret = -EINVAL;
791 goto out;
792 }
Yann Droneaud7efb1b12013-12-11 23:01:47 +0100793
Yann Droneaudf21519b2013-11-06 23:21:49 +0100794 if (ex_hdr.response) {
Yishai Hadas036b1062015-08-13 18:32:05 +0300795 if (!hdr.out_words && !ex_hdr.provider_out_words) {
796 ret = -EINVAL;
797 goto out;
798 }
Yann Droneaud6cc3df82013-12-11 23:01:51 +0100799
800 if (!access_ok(VERIFY_WRITE,
801 (void __user *) (unsigned long) ex_hdr.response,
Yishai Hadas036b1062015-08-13 18:32:05 +0300802 (hdr.out_words + ex_hdr.provider_out_words) * 8)) {
803 ret = -EFAULT;
804 goto out;
805 }
Yann Droneaudf21519b2013-11-06 23:21:49 +0100806 } else {
Yishai Hadas036b1062015-08-13 18:32:05 +0300807 if (hdr.out_words || ex_hdr.provider_out_words) {
808 ret = -EINVAL;
809 goto out;
810 }
Yann Droneaudf21519b2013-11-06 23:21:49 +0100811 }
812
Roland Dreiera96e4e22013-12-19 08:37:03 -0800813 INIT_UDATA_BUF_OR_NULL(&ucore, buf, (unsigned long) ex_hdr.response,
814 hdr.in_words * 8, hdr.out_words * 8);
Yann Droneaudf21519b2013-11-06 23:21:49 +0100815
Roland Dreiera96e4e22013-12-19 08:37:03 -0800816 INIT_UDATA_BUF_OR_NULL(&uhw,
817 buf + ucore.inlen,
818 (unsigned long) ex_hdr.response + ucore.outlen,
819 ex_hdr.provider_in_words * 8,
820 ex_hdr.provider_out_words * 8);
Yann Droneaudf21519b2013-11-06 23:21:49 +0100821
Yishai Hadas036b1062015-08-13 18:32:05 +0300822 ret = uverbs_ex_cmd_table[command](file,
Yishai Hadas057aec02015-08-13 18:32:04 +0300823 ib_dev,
Yann Droneaudf21519b2013-11-06 23:21:49 +0100824 &ucore,
825 &uhw);
Yishai Hadas036b1062015-08-13 18:32:05 +0300826 if (!ret)
827 ret = written_count;
828 } else {
829 ret = -ENOSYS;
Igor Ivanov400dbc92013-08-14 13:58:29 +0300830 }
Yann Droneaudf21519b2013-11-06 23:21:49 +0100831
Yishai Hadas036b1062015-08-13 18:32:05 +0300832out:
833 srcu_read_unlock(&file->device->disassociate_srcu, srcu_key);
834 return ret;
Roland Dreierbc38a6a2005-07-07 17:57:13 -0700835}
836
837static int ib_uverbs_mmap(struct file *filp, struct vm_area_struct *vma)
838{
839 struct ib_uverbs_file *file = filp->private_data;
Yishai Hadas036b1062015-08-13 18:32:05 +0300840 struct ib_device *ib_dev;
841 int ret = 0;
842 int srcu_key;
Roland Dreierbc38a6a2005-07-07 17:57:13 -0700843
Yishai Hadas036b1062015-08-13 18:32:05 +0300844 srcu_key = srcu_read_lock(&file->device->disassociate_srcu);
845 ib_dev = srcu_dereference(file->device->ib_dev,
846 &file->device->disassociate_srcu);
847 if (!ib_dev) {
848 ret = -EIO;
849 goto out;
850 }
851
852 if (!file->ucontext)
853 ret = -ENODEV;
Roland Dreierbc38a6a2005-07-07 17:57:13 -0700854 else
Yishai Hadas036b1062015-08-13 18:32:05 +0300855 ret = ib_dev->mmap(file->ucontext, vma);
856out:
857 srcu_read_unlock(&file->device->disassociate_srcu, srcu_key);
858 return ret;
Roland Dreierbc38a6a2005-07-07 17:57:13 -0700859}
860
Roland Dreier5b2d2812008-06-27 14:43:20 -0700861/*
862 * ib_uverbs_open() does not need the BKL:
863 *
Alexander Chiang2a72f212010-02-02 19:07:54 +0000864 * - the ib_uverbs_device structures are properly reference counted and
Roland Dreier5b2d2812008-06-27 14:43:20 -0700865 * everything else is purely local to the file being created, so
866 * races against other open calls are not a problem;
867 * - there is no ioctl method to race against;
Alexander Chiang2a72f212010-02-02 19:07:54 +0000868 * - the open method will either immediately run -ENXIO, or all
869 * required initialization will be done.
Roland Dreier5b2d2812008-06-27 14:43:20 -0700870 */
Roland Dreierbc38a6a2005-07-07 17:57:13 -0700871static int ib_uverbs_open(struct inode *inode, struct file *filp)
872{
Roland Dreier70a30e12005-10-28 15:38:26 -0700873 struct ib_uverbs_device *dev;
Roland Dreierbc38a6a2005-07-07 17:57:13 -0700874 struct ib_uverbs_file *file;
Yishai Hadas036b1062015-08-13 18:32:05 +0300875 struct ib_device *ib_dev;
Roland Dreier70a30e12005-10-28 15:38:26 -0700876 int ret;
Yishai Hadas036b1062015-08-13 18:32:05 +0300877 int module_dependent;
878 int srcu_key;
Roland Dreierbc38a6a2005-07-07 17:57:13 -0700879
Alexander Chiang2a72f212010-02-02 19:07:54 +0000880 dev = container_of(inode->i_cdev, struct ib_uverbs_device, cdev);
Yishai Hadas35d4a0b2015-08-13 18:32:03 +0300881 if (!atomic_inc_not_zero(&dev->refcount))
Roland Dreier70a30e12005-10-28 15:38:26 -0700882 return -ENXIO;
883
Yishai Hadas036b1062015-08-13 18:32:05 +0300884 srcu_key = srcu_read_lock(&dev->disassociate_srcu);
885 mutex_lock(&dev->lists_mutex);
886 ib_dev = srcu_dereference(dev->ib_dev,
887 &dev->disassociate_srcu);
888 if (!ib_dev) {
889 ret = -EIO;
Roland Dreier70a30e12005-10-28 15:38:26 -0700890 goto err;
891 }
Roland Dreierbc38a6a2005-07-07 17:57:13 -0700892
Yishai Hadas036b1062015-08-13 18:32:05 +0300893 /* In case IB device supports disassociate ucontext, there is no hard
894 * dependency between uverbs device and its low level device.
895 */
896 module_dependent = !(ib_dev->disassociate_ucontext);
897
898 if (module_dependent) {
899 if (!try_module_get(ib_dev->owner)) {
900 ret = -ENODEV;
901 goto err;
902 }
903 }
904
905 file = kzalloc(sizeof(*file), GFP_KERNEL);
Roland Dreier63c47c22005-09-26 13:01:03 -0700906 if (!file) {
Roland Dreier70a30e12005-10-28 15:38:26 -0700907 ret = -ENOMEM;
Yishai Hadas036b1062015-08-13 18:32:05 +0300908 if (module_dependent)
909 goto err_module;
910
911 goto err;
Roland Dreier63c47c22005-09-26 13:01:03 -0700912 }
Roland Dreierbc38a6a2005-07-07 17:57:13 -0700913
Roland Dreier70a30e12005-10-28 15:38:26 -0700914 file->device = dev;
915 file->ucontext = NULL;
916 file->async_file = NULL;
Roland Dreierbc38a6a2005-07-07 17:57:13 -0700917 kref_init(&file->ref);
Ingo Molnar95ed6442006-01-13 14:51:39 -0800918 mutex_init(&file->mutex);
Roland Dreierbc38a6a2005-07-07 17:57:13 -0700919
Roland Dreierbc38a6a2005-07-07 17:57:13 -0700920 filp->private_data = file;
Yishai Hadas35d4a0b2015-08-13 18:32:03 +0300921 kobject_get(&dev->kobj);
Yishai Hadas036b1062015-08-13 18:32:05 +0300922 list_add_tail(&file->list, &dev->uverbs_file_list);
923 mutex_unlock(&dev->lists_mutex);
924 srcu_read_unlock(&dev->disassociate_srcu, srcu_key);
Roland Dreierbc38a6a2005-07-07 17:57:13 -0700925
Roland Dreierbc1db9a2010-04-09 17:13:50 -0700926 return nonseekable_open(inode, filp);
Roland Dreier70a30e12005-10-28 15:38:26 -0700927
928err_module:
Yishai Hadas036b1062015-08-13 18:32:05 +0300929 module_put(ib_dev->owner);
Roland Dreier70a30e12005-10-28 15:38:26 -0700930
931err:
Yishai Hadas036b1062015-08-13 18:32:05 +0300932 mutex_unlock(&dev->lists_mutex);
933 srcu_read_unlock(&dev->disassociate_srcu, srcu_key);
Yishai Hadas35d4a0b2015-08-13 18:32:03 +0300934 if (atomic_dec_and_test(&dev->refcount))
935 ib_uverbs_comp_dev(dev);
936
Roland Dreier70a30e12005-10-28 15:38:26 -0700937 return ret;
Roland Dreierbc38a6a2005-07-07 17:57:13 -0700938}
939
940static int ib_uverbs_close(struct inode *inode, struct file *filp)
941{
942 struct ib_uverbs_file *file = filp->private_data;
Yishai Hadas35d4a0b2015-08-13 18:32:03 +0300943 struct ib_uverbs_device *dev = file->device;
Yishai Hadas036b1062015-08-13 18:32:05 +0300944 struct ib_ucontext *ucontext = NULL;
Roland Dreierbc38a6a2005-07-07 17:57:13 -0700945
Yishai Hadas036b1062015-08-13 18:32:05 +0300946 mutex_lock(&file->device->lists_mutex);
947 ucontext = file->ucontext;
948 file->ucontext = NULL;
949 if (!file->is_closed) {
950 list_del(&file->list);
951 file->is_closed = 1;
952 }
953 mutex_unlock(&file->device->lists_mutex);
954 if (ucontext)
955 ib_uverbs_cleanup_ucontext(file, ucontext);
Roland Dreierbc38a6a2005-07-07 17:57:13 -0700956
Roland Dreier70a30e12005-10-28 15:38:26 -0700957 if (file->async_file)
958 kref_put(&file->async_file->ref, ib_uverbs_release_event_file);
959
Roland Dreierbc38a6a2005-07-07 17:57:13 -0700960 kref_put(&file->ref, ib_uverbs_release_file);
Yishai Hadas35d4a0b2015-08-13 18:32:03 +0300961 kobject_put(&dev->kobj);
Roland Dreierbc38a6a2005-07-07 17:57:13 -0700962
963 return 0;
964}
965
Arjan van de Ven2b8693c2007-02-12 00:55:32 -0800966static const struct file_operations uverbs_fops = {
Alexander Chiang9afed762010-02-02 19:08:19 +0000967 .owner = THIS_MODULE,
968 .write = ib_uverbs_write,
969 .open = ib_uverbs_open,
Roland Dreierbc1db9a2010-04-09 17:13:50 -0700970 .release = ib_uverbs_close,
971 .llseek = no_llseek,
Roland Dreierbc38a6a2005-07-07 17:57:13 -0700972};
973
Arjan van de Ven2b8693c2007-02-12 00:55:32 -0800974static const struct file_operations uverbs_mmap_fops = {
Alexander Chiang9afed762010-02-02 19:08:19 +0000975 .owner = THIS_MODULE,
976 .write = ib_uverbs_write,
Roland Dreierbc38a6a2005-07-07 17:57:13 -0700977 .mmap = ib_uverbs_mmap,
Alexander Chiang9afed762010-02-02 19:08:19 +0000978 .open = ib_uverbs_open,
Roland Dreierbc1db9a2010-04-09 17:13:50 -0700979 .release = ib_uverbs_close,
980 .llseek = no_llseek,
Roland Dreierbc38a6a2005-07-07 17:57:13 -0700981};
982
983static struct ib_client uverbs_client = {
984 .name = "uverbs",
985 .add = ib_uverbs_add_one,
986 .remove = ib_uverbs_remove_one
987};
988
Tony Jonesf4e91eb2008-02-22 00:13:36 +0100989static ssize_t show_ibdev(struct device *device, struct device_attribute *attr,
990 char *buf)
Roland Dreierbc38a6a2005-07-07 17:57:13 -0700991{
Yishai Hadas036b1062015-08-13 18:32:05 +0300992 int ret = -ENODEV;
993 int srcu_key;
Tony Jonesf4e91eb2008-02-22 00:13:36 +0100994 struct ib_uverbs_device *dev = dev_get_drvdata(device);
Yishai Hadas036b1062015-08-13 18:32:05 +0300995 struct ib_device *ib_dev;
Roland Dreier70a30e12005-10-28 15:38:26 -0700996
997 if (!dev)
998 return -ENODEV;
Roland Dreierbc38a6a2005-07-07 17:57:13 -0700999
Yishai Hadas036b1062015-08-13 18:32:05 +03001000 srcu_key = srcu_read_lock(&dev->disassociate_srcu);
1001 ib_dev = srcu_dereference(dev->ib_dev, &dev->disassociate_srcu);
1002 if (ib_dev)
1003 ret = sprintf(buf, "%s\n", ib_dev->name);
1004 srcu_read_unlock(&dev->disassociate_srcu, srcu_key);
1005
1006 return ret;
Roland Dreierbc38a6a2005-07-07 17:57:13 -07001007}
Tony Jonesf4e91eb2008-02-22 00:13:36 +01001008static DEVICE_ATTR(ibdev, S_IRUGO, show_ibdev, NULL);
Roland Dreierbc38a6a2005-07-07 17:57:13 -07001009
Tony Jonesf4e91eb2008-02-22 00:13:36 +01001010static ssize_t show_dev_abi_version(struct device *device,
1011 struct device_attribute *attr, char *buf)
Roland Dreier274c0892005-09-29 14:17:48 -07001012{
Tony Jonesf4e91eb2008-02-22 00:13:36 +01001013 struct ib_uverbs_device *dev = dev_get_drvdata(device);
Yishai Hadas036b1062015-08-13 18:32:05 +03001014 int ret = -ENODEV;
1015 int srcu_key;
1016 struct ib_device *ib_dev;
Roland Dreier70a30e12005-10-28 15:38:26 -07001017
1018 if (!dev)
1019 return -ENODEV;
Yishai Hadas036b1062015-08-13 18:32:05 +03001020 srcu_key = srcu_read_lock(&dev->disassociate_srcu);
1021 ib_dev = srcu_dereference(dev->ib_dev, &dev->disassociate_srcu);
1022 if (ib_dev)
1023 ret = sprintf(buf, "%d\n", ib_dev->uverbs_abi_ver);
1024 srcu_read_unlock(&dev->disassociate_srcu, srcu_key);
Roland Dreier274c0892005-09-29 14:17:48 -07001025
Yishai Hadas036b1062015-08-13 18:32:05 +03001026 return ret;
Roland Dreier274c0892005-09-29 14:17:48 -07001027}
Tony Jonesf4e91eb2008-02-22 00:13:36 +01001028static DEVICE_ATTR(abi_version, S_IRUGO, show_dev_abi_version, NULL);
Roland Dreier274c0892005-09-29 14:17:48 -07001029
Andi Kleen0933e2d2010-01-05 12:48:09 +01001030static CLASS_ATTR_STRING(abi_version, S_IRUGO,
1031 __stringify(IB_USER_VERBS_ABI_VERSION));
Roland Dreierbc38a6a2005-07-07 17:57:13 -07001032
Alexander Chiang6d6a0e72010-02-02 19:08:09 +00001033static dev_t overflow_maj;
1034static DECLARE_BITMAP(overflow_map, IB_UVERBS_MAX_DEVICES);
1035
1036/*
1037 * If we have more than IB_UVERBS_MAX_DEVICES, dynamically overflow by
1038 * requesting a new major number and doubling the number of max devices we
1039 * support. It's stupid, but simple.
1040 */
1041static int find_overflow_devnum(void)
1042{
1043 int ret;
1044
1045 if (!overflow_maj) {
1046 ret = alloc_chrdev_region(&overflow_maj, 0, IB_UVERBS_MAX_DEVICES,
1047 "infiniband_verbs");
1048 if (ret) {
1049 printk(KERN_ERR "user_verbs: couldn't register dynamic device number\n");
1050 return ret;
1051 }
1052 }
1053
1054 ret = find_first_zero_bit(overflow_map, IB_UVERBS_MAX_DEVICES);
1055 if (ret >= IB_UVERBS_MAX_DEVICES)
1056 return -1;
1057
1058 return ret;
1059}
1060
Roland Dreierbc38a6a2005-07-07 17:57:13 -07001061static void ib_uverbs_add_one(struct ib_device *device)
1062{
Alexander Chiang38707982010-02-02 19:07:59 +00001063 int devnum;
Alexander Chiangddbd6882010-02-02 19:08:04 +00001064 dev_t base;
Roland Dreierbc38a6a2005-07-07 17:57:13 -07001065 struct ib_uverbs_device *uverbs_dev;
Yishai Hadas036b1062015-08-13 18:32:05 +03001066 int ret;
Roland Dreierbc38a6a2005-07-07 17:57:13 -07001067
1068 if (!device->alloc_ucontext)
1069 return;
1070
Roland Dreierde6eb662005-11-02 07:23:14 -08001071 uverbs_dev = kzalloc(sizeof *uverbs_dev, GFP_KERNEL);
Roland Dreierbc38a6a2005-07-07 17:57:13 -07001072 if (!uverbs_dev)
1073 return;
1074
Yishai Hadas036b1062015-08-13 18:32:05 +03001075 ret = init_srcu_struct(&uverbs_dev->disassociate_srcu);
1076 if (ret) {
1077 kfree(uverbs_dev);
1078 return;
1079 }
1080
Yishai Hadas35d4a0b2015-08-13 18:32:03 +03001081 atomic_set(&uverbs_dev->refcount, 1);
Jack Morgensteinfd60ae42006-08-03 10:56:42 -07001082 init_completion(&uverbs_dev->comp);
Sean Hefty53d0bd12011-05-24 08:33:46 -07001083 uverbs_dev->xrcd_tree = RB_ROOT;
1084 mutex_init(&uverbs_dev->xrcd_tree_mutex);
Yishai Hadas35d4a0b2015-08-13 18:32:03 +03001085 kobject_init(&uverbs_dev->kobj, &ib_uverbs_dev_ktype);
Yishai Hadas036b1062015-08-13 18:32:05 +03001086 mutex_init(&uverbs_dev->lists_mutex);
1087 INIT_LIST_HEAD(&uverbs_dev->uverbs_file_list);
1088 INIT_LIST_HEAD(&uverbs_dev->uverbs_events_file_list);
Roland Dreier70a30e12005-10-28 15:38:26 -07001089
Roland Dreierbc38a6a2005-07-07 17:57:13 -07001090 spin_lock(&map_lock);
Alexander Chiang38707982010-02-02 19:07:59 +00001091 devnum = find_first_zero_bit(dev_map, IB_UVERBS_MAX_DEVICES);
1092 if (devnum >= IB_UVERBS_MAX_DEVICES) {
Roland Dreierbc38a6a2005-07-07 17:57:13 -07001093 spin_unlock(&map_lock);
Alexander Chiang6d6a0e72010-02-02 19:08:09 +00001094 devnum = find_overflow_devnum();
1095 if (devnum < 0)
1096 goto err;
1097
1098 spin_lock(&map_lock);
1099 uverbs_dev->devnum = devnum + IB_UVERBS_MAX_DEVICES;
1100 base = devnum + overflow_maj;
1101 set_bit(devnum, overflow_map);
1102 } else {
1103 uverbs_dev->devnum = devnum;
1104 base = devnum + IB_UVERBS_BASE_DEV;
1105 set_bit(devnum, dev_map);
Roland Dreierbc38a6a2005-07-07 17:57:13 -07001106 }
Roland Dreierbc38a6a2005-07-07 17:57:13 -07001107 spin_unlock(&map_lock);
1108
Yishai Hadas036b1062015-08-13 18:32:05 +03001109 rcu_assign_pointer(uverbs_dev->ib_dev, device);
Michael S. Tsirkinf4fd0b22007-05-03 13:48:47 +03001110 uverbs_dev->num_comp_vectors = device->num_comp_vectors;
Roland Dreierbc38a6a2005-07-07 17:57:13 -07001111
Alexander Chiang055422d2010-02-02 19:07:49 +00001112 cdev_init(&uverbs_dev->cdev, NULL);
1113 uverbs_dev->cdev.owner = THIS_MODULE;
1114 uverbs_dev->cdev.ops = device->mmap ? &uverbs_mmap_fops : &uverbs_fops;
Yishai Hadas35d4a0b2015-08-13 18:32:03 +03001115 uverbs_dev->cdev.kobj.parent = &uverbs_dev->kobj;
Alexander Chiang055422d2010-02-02 19:07:49 +00001116 kobject_set_name(&uverbs_dev->cdev.kobj, "uverbs%d", uverbs_dev->devnum);
Alexander Chiangddbd6882010-02-02 19:08:04 +00001117 if (cdev_add(&uverbs_dev->cdev, base, 1))
Roland Dreierbc38a6a2005-07-07 17:57:13 -07001118 goto err_cdev;
1119
Greg Kroah-Hartman91bd4182008-07-21 20:03:34 -07001120 uverbs_dev->dev = device_create(uverbs_class, device->dma_device,
Alexander Chiang055422d2010-02-02 19:07:49 +00001121 uverbs_dev->cdev.dev, uverbs_dev,
Greg Kroah-Hartman91bd4182008-07-21 20:03:34 -07001122 "uverbs%d", uverbs_dev->devnum);
Tony Jonesf4e91eb2008-02-22 00:13:36 +01001123 if (IS_ERR(uverbs_dev->dev))
Roland Dreier70a30e12005-10-28 15:38:26 -07001124 goto err_cdev;
1125
Tony Jonesf4e91eb2008-02-22 00:13:36 +01001126 if (device_create_file(uverbs_dev->dev, &dev_attr_ibdev))
Roland Dreierbc38a6a2005-07-07 17:57:13 -07001127 goto err_class;
Tony Jonesf4e91eb2008-02-22 00:13:36 +01001128 if (device_create_file(uverbs_dev->dev, &dev_attr_abi_version))
Roland Dreier274c0892005-09-29 14:17:48 -07001129 goto err_class;
Roland Dreierbc38a6a2005-07-07 17:57:13 -07001130
1131 ib_set_client_data(device, &uverbs_client, uverbs_dev);
1132
1133 return;
1134
1135err_class:
Alexander Chiang055422d2010-02-02 19:07:49 +00001136 device_destroy(uverbs_class, uverbs_dev->cdev.dev);
Roland Dreierbc38a6a2005-07-07 17:57:13 -07001137
1138err_cdev:
Alexander Chiang055422d2010-02-02 19:07:49 +00001139 cdev_del(&uverbs_dev->cdev);
Alexander Chiang6d6a0e72010-02-02 19:08:09 +00001140 if (uverbs_dev->devnum < IB_UVERBS_MAX_DEVICES)
1141 clear_bit(devnum, dev_map);
1142 else
1143 clear_bit(devnum, overflow_map);
Roland Dreierbc38a6a2005-07-07 17:57:13 -07001144
1145err:
Yishai Hadas35d4a0b2015-08-13 18:32:03 +03001146 if (atomic_dec_and_test(&uverbs_dev->refcount))
1147 ib_uverbs_comp_dev(uverbs_dev);
Jack Morgensteinfd60ae42006-08-03 10:56:42 -07001148 wait_for_completion(&uverbs_dev->comp);
Yishai Hadas35d4a0b2015-08-13 18:32:03 +03001149 kobject_put(&uverbs_dev->kobj);
Roland Dreierbc38a6a2005-07-07 17:57:13 -07001150 return;
1151}
1152
Yishai Hadas036b1062015-08-13 18:32:05 +03001153static void ib_uverbs_free_hw_resources(struct ib_uverbs_device *uverbs_dev,
1154 struct ib_device *ib_dev)
1155{
1156 struct ib_uverbs_file *file;
1157 struct ib_uverbs_event_file *event_file;
1158 struct ib_event event;
1159
1160 /* Pending running commands to terminate */
1161 synchronize_srcu(&uverbs_dev->disassociate_srcu);
1162 event.event = IB_EVENT_DEVICE_FATAL;
1163 event.element.port_num = 0;
1164 event.device = ib_dev;
1165
1166 mutex_lock(&uverbs_dev->lists_mutex);
1167 while (!list_empty(&uverbs_dev->uverbs_file_list)) {
1168 struct ib_ucontext *ucontext;
1169
1170 file = list_first_entry(&uverbs_dev->uverbs_file_list,
1171 struct ib_uverbs_file, list);
1172 file->is_closed = 1;
1173 ucontext = file->ucontext;
1174 list_del(&file->list);
1175 file->ucontext = NULL;
1176 kref_get(&file->ref);
1177 mutex_unlock(&uverbs_dev->lists_mutex);
1178 /* We must release the mutex before going ahead and calling
1179 * disassociate_ucontext. disassociate_ucontext might end up
1180 * indirectly calling uverbs_close, for example due to freeing
1181 * the resources (e.g mmput).
1182 */
1183 ib_uverbs_event_handler(&file->event_handler, &event);
1184 if (ucontext) {
1185 ib_dev->disassociate_ucontext(ucontext);
1186 ib_uverbs_cleanup_ucontext(file, ucontext);
1187 }
1188
1189 mutex_lock(&uverbs_dev->lists_mutex);
1190 kref_put(&file->ref, ib_uverbs_release_file);
1191 }
1192
1193 while (!list_empty(&uverbs_dev->uverbs_events_file_list)) {
1194 event_file = list_first_entry(&uverbs_dev->
1195 uverbs_events_file_list,
1196 struct ib_uverbs_event_file,
1197 list);
1198 spin_lock_irq(&event_file->lock);
1199 event_file->is_closed = 1;
1200 spin_unlock_irq(&event_file->lock);
1201
1202 list_del(&event_file->list);
1203 if (event_file->is_async) {
1204 ib_unregister_event_handler(&event_file->uverbs_file->
1205 event_handler);
1206 event_file->uverbs_file->event_handler.device = NULL;
1207 }
1208
1209 wake_up_interruptible(&event_file->poll_wait);
1210 kill_fasync(&event_file->async_queue, SIGIO, POLL_IN);
1211 }
1212 mutex_unlock(&uverbs_dev->lists_mutex);
1213}
1214
Haggai Eran7c1eb452015-07-30 17:50:14 +03001215static void ib_uverbs_remove_one(struct ib_device *device, void *client_data)
Roland Dreierbc38a6a2005-07-07 17:57:13 -07001216{
Haggai Eran7c1eb452015-07-30 17:50:14 +03001217 struct ib_uverbs_device *uverbs_dev = client_data;
Yishai Hadas036b1062015-08-13 18:32:05 +03001218 int wait_clients = 1;
Roland Dreierbc38a6a2005-07-07 17:57:13 -07001219
1220 if (!uverbs_dev)
1221 return;
1222
Tony Jonesf4e91eb2008-02-22 00:13:36 +01001223 dev_set_drvdata(uverbs_dev->dev, NULL);
Alexander Chiang055422d2010-02-02 19:07:49 +00001224 device_destroy(uverbs_class, uverbs_dev->cdev.dev);
1225 cdev_del(&uverbs_dev->cdev);
Roland Dreier70a30e12005-10-28 15:38:26 -07001226
Alexander Chiang6d6a0e72010-02-02 19:08:09 +00001227 if (uverbs_dev->devnum < IB_UVERBS_MAX_DEVICES)
1228 clear_bit(uverbs_dev->devnum, dev_map);
1229 else
1230 clear_bit(uverbs_dev->devnum - IB_UVERBS_MAX_DEVICES, overflow_map);
Jack Morgensteinfd60ae42006-08-03 10:56:42 -07001231
Yishai Hadas036b1062015-08-13 18:32:05 +03001232 if (device->disassociate_ucontext) {
1233 /* We disassociate HW resources and immediately return.
1234 * Userspace will see a EIO errno for all future access.
1235 * Upon returning, ib_device may be freed internally and is not
1236 * valid any more.
1237 * uverbs_device is still available until all clients close
1238 * their files, then the uverbs device ref count will be zero
1239 * and its resources will be freed.
1240 * Note: At this point no more files can be opened since the
1241 * cdev was deleted, however active clients can still issue
1242 * commands and close their open files.
1243 */
1244 rcu_assign_pointer(uverbs_dev->ib_dev, NULL);
1245 ib_uverbs_free_hw_resources(uverbs_dev, device);
1246 wait_clients = 0;
1247 }
1248
Yishai Hadas35d4a0b2015-08-13 18:32:03 +03001249 if (atomic_dec_and_test(&uverbs_dev->refcount))
1250 ib_uverbs_comp_dev(uverbs_dev);
Yishai Hadas036b1062015-08-13 18:32:05 +03001251 if (wait_clients)
1252 wait_for_completion(&uverbs_dev->comp);
Yishai Hadas35d4a0b2015-08-13 18:32:03 +03001253 kobject_put(&uverbs_dev->kobj);
Roland Dreierbc38a6a2005-07-07 17:57:13 -07001254}
1255
Al Viro2c9ede52011-07-23 20:24:48 -04001256static char *uverbs_devnode(struct device *dev, umode_t *mode)
Roland Dreier71c29bd2011-05-23 11:10:05 -07001257{
Goldwyn Rodriguesb2bc47822011-07-04 09:26:57 -07001258 if (mode)
1259 *mode = 0666;
Roland Dreier71c29bd2011-05-23 11:10:05 -07001260 return kasprintf(GFP_KERNEL, "infiniband/%s", dev_name(dev));
1261}
1262
Roland Dreierbc38a6a2005-07-07 17:57:13 -07001263static int __init ib_uverbs_init(void)
1264{
1265 int ret;
1266
Roland Dreierbc38a6a2005-07-07 17:57:13 -07001267 ret = register_chrdev_region(IB_UVERBS_BASE_DEV, IB_UVERBS_MAX_DEVICES,
1268 "infiniband_verbs");
1269 if (ret) {
1270 printk(KERN_ERR "user_verbs: couldn't register device number\n");
1271 goto out;
1272 }
1273
Roland Dreier70a30e12005-10-28 15:38:26 -07001274 uverbs_class = class_create(THIS_MODULE, "infiniband_verbs");
1275 if (IS_ERR(uverbs_class)) {
1276 ret = PTR_ERR(uverbs_class);
Roland Dreierbc38a6a2005-07-07 17:57:13 -07001277 printk(KERN_ERR "user_verbs: couldn't create class infiniband_verbs\n");
1278 goto out_chrdev;
1279 }
1280
Roland Dreier71c29bd2011-05-23 11:10:05 -07001281 uverbs_class->devnode = uverbs_devnode;
1282
Andi Kleen0933e2d2010-01-05 12:48:09 +01001283 ret = class_create_file(uverbs_class, &class_attr_abi_version.attr);
Roland Dreierbc38a6a2005-07-07 17:57:13 -07001284 if (ret) {
1285 printk(KERN_ERR "user_verbs: couldn't create abi_version attribute\n");
1286 goto out_class;
1287 }
1288
Roland Dreierbc38a6a2005-07-07 17:57:13 -07001289 ret = ib_register_client(&uverbs_client);
1290 if (ret) {
1291 printk(KERN_ERR "user_verbs: couldn't register client\n");
Roland Dreiera265e552010-02-24 16:51:20 -08001292 goto out_class;
Roland Dreierbc38a6a2005-07-07 17:57:13 -07001293 }
1294
1295 return 0;
1296
Roland Dreierbc38a6a2005-07-07 17:57:13 -07001297out_class:
Roland Dreier70a30e12005-10-28 15:38:26 -07001298 class_destroy(uverbs_class);
Roland Dreierbc38a6a2005-07-07 17:57:13 -07001299
1300out_chrdev:
1301 unregister_chrdev_region(IB_UVERBS_BASE_DEV, IB_UVERBS_MAX_DEVICES);
1302
1303out:
1304 return ret;
1305}
1306
1307static void __exit ib_uverbs_cleanup(void)
1308{
1309 ib_unregister_client(&uverbs_client);
Roland Dreier70a30e12005-10-28 15:38:26 -07001310 class_destroy(uverbs_class);
Roland Dreierbc38a6a2005-07-07 17:57:13 -07001311 unregister_chrdev_region(IB_UVERBS_BASE_DEV, IB_UVERBS_MAX_DEVICES);
Alexander Chiang6d6a0e72010-02-02 19:08:09 +00001312 if (overflow_maj)
1313 unregister_chrdev_region(overflow_maj, IB_UVERBS_MAX_DEVICES);
Roland Dreier5d7edb32005-10-24 10:53:25 -07001314 idr_destroy(&ib_uverbs_pd_idr);
1315 idr_destroy(&ib_uverbs_mr_idr);
1316 idr_destroy(&ib_uverbs_mw_idr);
1317 idr_destroy(&ib_uverbs_ah_idr);
1318 idr_destroy(&ib_uverbs_cq_idr);
1319 idr_destroy(&ib_uverbs_qp_idr);
1320 idr_destroy(&ib_uverbs_srq_idr);
Roland Dreierbc38a6a2005-07-07 17:57:13 -07001321}
1322
1323module_init(ib_uverbs_init);
1324module_exit(ib_uverbs_cleanup);