]> bbs.cooldavid.org Git - net-next-2.6.git/blame - drivers/infiniband/core/uverbs_main.c
driver-core: Add attribute argument to class_attribute show/store
[net-next-2.6.git] / drivers / infiniband / core / uverbs_main.c
CommitLineData
bc38a6ab
RD
1/*
2 * Copyright (c) 2005 Topspin Communications. All rights reserved.
33b9b3ee 3 * Copyright (c) 2005, 2006 Cisco Systems. All rights reserved.
2a1d9b7f
RD
4 * Copyright (c) 2005 Mellanox Technologies. All rights reserved.
5 * Copyright (c) 2005 Voltaire, Inc. All rights reserved.
67cdb40c 6 * Copyright (c) 2005 PathScale, Inc. All rights reserved.
bc38a6ab
RD
7 *
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.
bc38a6ab
RD
35 */
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>
a99bbaf5 43#include <linux/sched.h>
bc38a6ab 44#include <linux/file.h>
70a30e16 45#include <linux/cdev.h>
a265e558 46#include <linux/anon_inodes.h>
bc38a6ab
RD
47
48#include <asm/uaccess.h>
49
50#include "uverbs.h"
51
52MODULE_AUTHOR("Roland Dreier");
53MODULE_DESCRIPTION("InfiniBand userspace verbs access");
54MODULE_LICENSE("Dual BSD/GPL");
55
bc38a6ab
RD
56enum {
57 IB_UVERBS_MAJOR = 231,
58 IB_UVERBS_BASE_MINOR = 192,
59 IB_UVERBS_MAX_DEVICES = 32
60};
61
62#define IB_UVERBS_BASE_DEV MKDEV(IB_UVERBS_MAJOR, IB_UVERBS_BASE_MINOR)
63
70a30e16
RD
64static struct class *uverbs_class;
65
9ead190b 66DEFINE_SPINLOCK(ib_uverbs_idr_lock);
bc38a6ab
RD
67DEFINE_IDR(ib_uverbs_pd_idr);
68DEFINE_IDR(ib_uverbs_mr_idr);
69DEFINE_IDR(ib_uverbs_mw_idr);
70DEFINE_IDR(ib_uverbs_ah_idr);
71DEFINE_IDR(ib_uverbs_cq_idr);
72DEFINE_IDR(ib_uverbs_qp_idr);
f520ba5a 73DEFINE_IDR(ib_uverbs_srq_idr);
bc38a6ab 74
6276e08a 75static DEFINE_SPINLOCK(map_lock);
bc38a6ab
RD
76static DECLARE_BITMAP(dev_map, IB_UVERBS_MAX_DEVICES);
77
78static ssize_t (*uverbs_cmd_table[])(struct ib_uverbs_file *file,
79 const char __user *buf, int in_len,
80 int out_len) = {
9afed76d
AC
81 [IB_USER_VERBS_CMD_GET_CONTEXT] = ib_uverbs_get_context,
82 [IB_USER_VERBS_CMD_QUERY_DEVICE] = ib_uverbs_query_device,
83 [IB_USER_VERBS_CMD_QUERY_PORT] = ib_uverbs_query_port,
84 [IB_USER_VERBS_CMD_ALLOC_PD] = ib_uverbs_alloc_pd,
85 [IB_USER_VERBS_CMD_DEALLOC_PD] = ib_uverbs_dealloc_pd,
86 [IB_USER_VERBS_CMD_REG_MR] = ib_uverbs_reg_mr,
87 [IB_USER_VERBS_CMD_DEREG_MR] = ib_uverbs_dereg_mr,
6b73597e 88 [IB_USER_VERBS_CMD_CREATE_COMP_CHANNEL] = ib_uverbs_create_comp_channel,
9afed76d
AC
89 [IB_USER_VERBS_CMD_CREATE_CQ] = ib_uverbs_create_cq,
90 [IB_USER_VERBS_CMD_RESIZE_CQ] = ib_uverbs_resize_cq,
91 [IB_USER_VERBS_CMD_POLL_CQ] = ib_uverbs_poll_cq,
92 [IB_USER_VERBS_CMD_REQ_NOTIFY_CQ] = ib_uverbs_req_notify_cq,
93 [IB_USER_VERBS_CMD_DESTROY_CQ] = ib_uverbs_destroy_cq,
94 [IB_USER_VERBS_CMD_CREATE_QP] = ib_uverbs_create_qp,
95 [IB_USER_VERBS_CMD_QUERY_QP] = ib_uverbs_query_qp,
96 [IB_USER_VERBS_CMD_MODIFY_QP] = ib_uverbs_modify_qp,
97 [IB_USER_VERBS_CMD_DESTROY_QP] = ib_uverbs_destroy_qp,
98 [IB_USER_VERBS_CMD_POST_SEND] = ib_uverbs_post_send,
99 [IB_USER_VERBS_CMD_POST_RECV] = ib_uverbs_post_recv,
100 [IB_USER_VERBS_CMD_POST_SRQ_RECV] = ib_uverbs_post_srq_recv,
101 [IB_USER_VERBS_CMD_CREATE_AH] = ib_uverbs_create_ah,
102 [IB_USER_VERBS_CMD_DESTROY_AH] = ib_uverbs_destroy_ah,
103 [IB_USER_VERBS_CMD_ATTACH_MCAST] = ib_uverbs_attach_mcast,
104 [IB_USER_VERBS_CMD_DETACH_MCAST] = ib_uverbs_detach_mcast,
105 [IB_USER_VERBS_CMD_CREATE_SRQ] = ib_uverbs_create_srq,
106 [IB_USER_VERBS_CMD_MODIFY_SRQ] = ib_uverbs_modify_srq,
107 [IB_USER_VERBS_CMD_QUERY_SRQ] = ib_uverbs_query_srq,
108 [IB_USER_VERBS_CMD_DESTROY_SRQ] = ib_uverbs_destroy_srq,
bc38a6ab
RD
109};
110
bc38a6ab
RD
111static void ib_uverbs_add_one(struct ib_device *device);
112static void ib_uverbs_remove_one(struct ib_device *device);
113
70a30e16
RD
114static void ib_uverbs_release_dev(struct kref *ref)
115{
116 struct ib_uverbs_device *dev =
117 container_of(ref, struct ib_uverbs_device, ref);
118
fd60ae40 119 complete(&dev->comp);
70a30e16
RD
120}
121
04d29b0e
RD
122static void ib_uverbs_release_event_file(struct kref *ref)
123{
124 struct ib_uverbs_event_file *file =
125 container_of(ref, struct ib_uverbs_event_file, ref);
126
127 kfree(file);
128}
129
70a30e16
RD
130void ib_uverbs_release_ucq(struct ib_uverbs_file *file,
131 struct ib_uverbs_event_file *ev_file,
132 struct ib_ucq_object *uobj)
133{
134 struct ib_uverbs_event *evt, *tmp;
135
136 if (ev_file) {
137 spin_lock_irq(&ev_file->lock);
138 list_for_each_entry_safe(evt, tmp, &uobj->comp_list, obj_list) {
139 list_del(&evt->list);
140 kfree(evt);
141 }
142 spin_unlock_irq(&ev_file->lock);
143
144 kref_put(&ev_file->ref, ib_uverbs_release_event_file);
145 }
146
147 spin_lock_irq(&file->async_file->lock);
148 list_for_each_entry_safe(evt, tmp, &uobj->async_list, obj_list) {
149 list_del(&evt->list);
150 kfree(evt);
151 }
152 spin_unlock_irq(&file->async_file->lock);
153}
154
155void ib_uverbs_release_uevent(struct ib_uverbs_file *file,
156 struct ib_uevent_object *uobj)
157{
158 struct ib_uverbs_event *evt, *tmp;
159
160 spin_lock_irq(&file->async_file->lock);
161 list_for_each_entry_safe(evt, tmp, &uobj->event_list, obj_list) {
162 list_del(&evt->list);
163 kfree(evt);
164 }
165 spin_unlock_irq(&file->async_file->lock);
166}
167
f4e40156
JM
168static void ib_uverbs_detach_umcast(struct ib_qp *qp,
169 struct ib_uqp_object *uobj)
170{
171 struct ib_uverbs_mcast_entry *mcast, *tmp;
172
173 list_for_each_entry_safe(mcast, tmp, &uobj->mcast_list, list) {
174 ib_detach_mcast(qp, &mcast->gid, mcast->lid);
175 list_del(&mcast->list);
176 kfree(mcast);
177 }
178}
179
70a30e16
RD
180static int ib_uverbs_cleanup_ucontext(struct ib_uverbs_file *file,
181 struct ib_ucontext *context)
bc38a6ab
RD
182{
183 struct ib_uobject *uobj, *tmp;
184
185 if (!context)
186 return 0;
187
f7c6a7b5
RD
188 context->closing = 1;
189
67cdb40c 190 list_for_each_entry_safe(uobj, tmp, &context->ah_list, list) {
9ead190b
RD
191 struct ib_ah *ah = uobj->object;
192
193 idr_remove_uobj(&ib_uverbs_ah_idr, uobj);
67cdb40c 194 ib_destroy_ah(ah);
67cdb40c
RD
195 kfree(uobj);
196 }
bc38a6ab
RD
197
198 list_for_each_entry_safe(uobj, tmp, &context->qp_list, list) {
9ead190b 199 struct ib_qp *qp = uobj->object;
f4e40156
JM
200 struct ib_uqp_object *uqp =
201 container_of(uobj, struct ib_uqp_object, uevent.uobject);
9ead190b
RD
202
203 idr_remove_uobj(&ib_uverbs_qp_idr, uobj);
f4e40156 204 ib_uverbs_detach_umcast(qp, uqp);
bc38a6ab 205 ib_destroy_qp(qp);
f4e40156
JM
206 ib_uverbs_release_uevent(file, &uqp->uevent);
207 kfree(uqp);
bc38a6ab
RD
208 }
209
210 list_for_each_entry_safe(uobj, tmp, &context->cq_list, list) {
9ead190b 211 struct ib_cq *cq = uobj->object;
70a30e16
RD
212 struct ib_uverbs_event_file *ev_file = cq->cq_context;
213 struct ib_ucq_object *ucq =
214 container_of(uobj, struct ib_ucq_object, uobject);
9ead190b
RD
215
216 idr_remove_uobj(&ib_uverbs_cq_idr, uobj);
bc38a6ab 217 ib_destroy_cq(cq);
70a30e16
RD
218 ib_uverbs_release_ucq(file, ev_file, ucq);
219 kfree(ucq);
bc38a6ab
RD
220 }
221
f520ba5a 222 list_for_each_entry_safe(uobj, tmp, &context->srq_list, list) {
9ead190b 223 struct ib_srq *srq = uobj->object;
70a30e16
RD
224 struct ib_uevent_object *uevent =
225 container_of(uobj, struct ib_uevent_object, uobject);
9ead190b
RD
226
227 idr_remove_uobj(&ib_uverbs_srq_idr, uobj);
f520ba5a 228 ib_destroy_srq(srq);
70a30e16
RD
229 ib_uverbs_release_uevent(file, uevent);
230 kfree(uevent);
f520ba5a
RD
231 }
232
bc38a6ab
RD
233 /* XXX Free MWs */
234
235 list_for_each_entry_safe(uobj, tmp, &context->mr_list, list) {
9ead190b 236 struct ib_mr *mr = uobj->object;
bc38a6ab 237
9ead190b 238 idr_remove_uobj(&ib_uverbs_mr_idr, uobj);
bc38a6ab 239 ib_dereg_mr(mr);
f7c6a7b5 240 kfree(uobj);
bc38a6ab
RD
241 }
242
243 list_for_each_entry_safe(uobj, tmp, &context->pd_list, list) {
9ead190b
RD
244 struct ib_pd *pd = uobj->object;
245
246 idr_remove_uobj(&ib_uverbs_pd_idr, uobj);
bc38a6ab 247 ib_dealloc_pd(pd);
bc38a6ab
RD
248 kfree(uobj);
249 }
250
bc38a6ab
RD
251 return context->device->dealloc_ucontext(context);
252}
253
254static void ib_uverbs_release_file(struct kref *ref)
255{
256 struct ib_uverbs_file *file =
257 container_of(ref, struct ib_uverbs_file, ref);
258
259 module_put(file->device->ib_dev->owner);
70a30e16
RD
260 kref_put(&file->device->ref, ib_uverbs_release_dev);
261
bc38a6ab
RD
262 kfree(file);
263}
264
265static ssize_t ib_uverbs_event_read(struct file *filp, char __user *buf,
266 size_t count, loff_t *pos)
267{
268 struct ib_uverbs_event_file *file = filp->private_data;
63aaf647 269 struct ib_uverbs_event *event;
bc38a6ab
RD
270 int eventsz;
271 int ret = 0;
272
273 spin_lock_irq(&file->lock);
274
6b73597e 275 while (list_empty(&file->event_list)) {
bc38a6ab
RD
276 spin_unlock_irq(&file->lock);
277
278 if (filp->f_flags & O_NONBLOCK)
279 return -EAGAIN;
280
281 if (wait_event_interruptible(file->poll_wait,
6b73597e 282 !list_empty(&file->event_list)))
bc38a6ab
RD
283 return -ERESTARTSYS;
284
285 spin_lock_irq(&file->lock);
286 }
287
63aaf647
RD
288 event = list_entry(file->event_list.next, struct ib_uverbs_event, list);
289
290 if (file->is_async)
bc38a6ab 291 eventsz = sizeof (struct ib_uverbs_async_event_desc);
63aaf647 292 else
bc38a6ab 293 eventsz = sizeof (struct ib_uverbs_comp_event_desc);
bc38a6ab
RD
294
295 if (eventsz > count) {
296 ret = -EINVAL;
297 event = NULL;
63aaf647 298 } else {
bc38a6ab 299 list_del(file->event_list.next);
63aaf647
RD
300 if (event->counter) {
301 ++(*event->counter);
302 list_del(&event->obj_list);
303 }
304 }
bc38a6ab
RD
305
306 spin_unlock_irq(&file->lock);
307
308 if (event) {
309 if (copy_to_user(buf, event, eventsz))
310 ret = -EFAULT;
311 else
312 ret = eventsz;
313 }
314
315 kfree(event);
316
317 return ret;
318}
319
320static unsigned int ib_uverbs_event_poll(struct file *filp,
321 struct poll_table_struct *wait)
322{
323 unsigned int pollflags = 0;
324 struct ib_uverbs_event_file *file = filp->private_data;
325
326 poll_wait(filp, &file->poll_wait, wait);
327
328 spin_lock_irq(&file->lock);
6b73597e 329 if (!list_empty(&file->event_list))
bc38a6ab
RD
330 pollflags = POLLIN | POLLRDNORM;
331 spin_unlock_irq(&file->lock);
332
333 return pollflags;
334}
335
abdf119b
GN
336static int ib_uverbs_event_fasync(int fd, struct file *filp, int on)
337{
338 struct ib_uverbs_event_file *file = filp->private_data;
339
340 return fasync_helper(fd, filp, on, &file->async_queue);
341}
342
bc38a6ab
RD
343static int ib_uverbs_event_close(struct inode *inode, struct file *filp)
344{
345 struct ib_uverbs_event_file *file = filp->private_data;
6b73597e
RD
346 struct ib_uverbs_event *entry, *tmp;
347
348 spin_lock_irq(&file->lock);
1ae5c187 349 file->is_closed = 1;
6b73597e
RD
350 list_for_each_entry_safe(entry, tmp, &file->event_list, list) {
351 if (entry->counter)
352 list_del(&entry->obj_list);
353 kfree(entry);
354 }
355 spin_unlock_irq(&file->lock);
bc38a6ab 356
6b73597e
RD
357 if (file->is_async) {
358 ib_unregister_event_handler(&file->uverbs_file->event_handler);
359 kref_put(&file->uverbs_file->ref, ib_uverbs_release_file);
360 }
361 kref_put(&file->ref, ib_uverbs_release_event_file);
bc38a6ab
RD
362
363 return 0;
364}
365
2b8693c0 366static const struct file_operations uverbs_event_fops = {
6b73597e 367 .owner = THIS_MODULE,
9afed76d 368 .read = ib_uverbs_event_read,
bc38a6ab 369 .poll = ib_uverbs_event_poll,
abdf119b
GN
370 .release = ib_uverbs_event_close,
371 .fasync = ib_uverbs_event_fasync
bc38a6ab
RD
372};
373
374void ib_uverbs_comp_handler(struct ib_cq *cq, void *cq_context)
375{
6b73597e
RD
376 struct ib_uverbs_event_file *file = cq_context;
377 struct ib_ucq_object *uobj;
378 struct ib_uverbs_event *entry;
379 unsigned long flags;
380
381 if (!file)
382 return;
383
384 spin_lock_irqsave(&file->lock, flags);
1ae5c187 385 if (file->is_closed) {
6b73597e
RD
386 spin_unlock_irqrestore(&file->lock, flags);
387 return;
388 }
bc38a6ab
RD
389
390 entry = kmalloc(sizeof *entry, GFP_ATOMIC);
305a7e87
RD
391 if (!entry) {
392 spin_unlock_irqrestore(&file->lock, flags);
bc38a6ab 393 return;
305a7e87 394 }
bc38a6ab 395
63aaf647
RD
396 uobj = container_of(cq->uobject, struct ib_ucq_object, uobject);
397
398 entry->desc.comp.cq_handle = cq->uobject->user_handle;
399 entry->counter = &uobj->comp_events_reported;
bc38a6ab 400
6b73597e 401 list_add_tail(&entry->list, &file->event_list);
63aaf647 402 list_add_tail(&entry->obj_list, &uobj->comp_list);
6b73597e 403 spin_unlock_irqrestore(&file->lock, flags);
bc38a6ab 404
6b73597e
RD
405 wake_up_interruptible(&file->poll_wait);
406 kill_fasync(&file->async_queue, SIGIO, POLL_IN);
bc38a6ab
RD
407}
408
409static void ib_uverbs_async_handler(struct ib_uverbs_file *file,
63aaf647
RD
410 __u64 element, __u64 event,
411 struct list_head *obj_list,
412 u32 *counter)
bc38a6ab 413{
63aaf647 414 struct ib_uverbs_event *entry;
bc38a6ab
RD
415 unsigned long flags;
416
6b73597e 417 spin_lock_irqsave(&file->async_file->lock, flags);
fb77bcef 418 if (file->async_file->is_closed) {
6b73597e
RD
419 spin_unlock_irqrestore(&file->async_file->lock, flags);
420 return;
421 }
422
bc38a6ab 423 entry = kmalloc(sizeof *entry, GFP_ATOMIC);
305a7e87
RD
424 if (!entry) {
425 spin_unlock_irqrestore(&file->async_file->lock, flags);
bc38a6ab 426 return;
305a7e87 427 }
bc38a6ab 428
63aaf647
RD
429 entry->desc.async.element = element;
430 entry->desc.async.event_type = event;
431 entry->counter = counter;
bc38a6ab 432
6b73597e 433 list_add_tail(&entry->list, &file->async_file->event_list);
63aaf647
RD
434 if (obj_list)
435 list_add_tail(&entry->obj_list, obj_list);
6b73597e 436 spin_unlock_irqrestore(&file->async_file->lock, flags);
bc38a6ab 437
6b73597e
RD
438 wake_up_interruptible(&file->async_file->poll_wait);
439 kill_fasync(&file->async_file->async_queue, SIGIO, POLL_IN);
bc38a6ab
RD
440}
441
442void ib_uverbs_cq_event_handler(struct ib_event *event, void *context_ptr)
443{
7162a3e0
RD
444 struct ib_ucq_object *uobj = container_of(event->element.cq->uobject,
445 struct ib_ucq_object, uobject);
63aaf647 446
7162a3e0 447 ib_uverbs_async_handler(uobj->uverbs_file, uobj->uobject.user_handle,
63aaf647
RD
448 event->event, &uobj->async_list,
449 &uobj->async_events_reported);
bc38a6ab
RD
450}
451
452void ib_uverbs_qp_event_handler(struct ib_event *event, void *context_ptr)
453{
63aaf647
RD
454 struct ib_uevent_object *uobj;
455
456 uobj = container_of(event->element.qp->uobject,
457 struct ib_uevent_object, uobject);
458
459 ib_uverbs_async_handler(context_ptr, uobj->uobject.user_handle,
460 event->event, &uobj->event_list,
461 &uobj->events_reported);
bc38a6ab
RD
462}
463
f520ba5a
RD
464void ib_uverbs_srq_event_handler(struct ib_event *event, void *context_ptr)
465{
63aaf647
RD
466 struct ib_uevent_object *uobj;
467
468 uobj = container_of(event->element.srq->uobject,
469 struct ib_uevent_object, uobject);
470
471 ib_uverbs_async_handler(context_ptr, uobj->uobject.user_handle,
472 event->event, &uobj->event_list,
473 &uobj->events_reported);
f520ba5a
RD
474}
475
6b73597e
RD
476void ib_uverbs_event_handler(struct ib_event_handler *handler,
477 struct ib_event *event)
bc38a6ab
RD
478{
479 struct ib_uverbs_file *file =
480 container_of(handler, struct ib_uverbs_file, event_handler);
481
63aaf647
RD
482 ib_uverbs_async_handler(file, event->element.port_num, event->event,
483 NULL, NULL);
bc38a6ab
RD
484}
485
6b73597e 486struct file *ib_uverbs_alloc_event_file(struct ib_uverbs_file *uverbs_file,
b1e4594b 487 int is_async)
bc38a6ab 488{
6b73597e 489 struct ib_uverbs_event_file *ev_file;
bc38a6ab
RD
490 struct file *filp;
491
6b73597e
RD
492 ev_file = kmalloc(sizeof *ev_file, GFP_KERNEL);
493 if (!ev_file)
494 return ERR_PTR(-ENOMEM);
495
496 kref_init(&ev_file->ref);
497 spin_lock_init(&ev_file->lock);
498 INIT_LIST_HEAD(&ev_file->event_list);
499 init_waitqueue_head(&ev_file->poll_wait);
500 ev_file->uverbs_file = uverbs_file;
501 ev_file->async_queue = NULL;
502 ev_file->is_async = is_async;
1ae5c187 503 ev_file->is_closed = 0;
6b73597e 504
b1e4594b 505 filp = anon_inode_getfile("[infinibandevent]", &uverbs_event_fops,
a265e558 506 ev_file, O_RDONLY);
b1e4594b
AV
507 if (IS_ERR(filp))
508 kfree(ev_file);
a7dab9e8 509
6b73597e 510 return filp;
6b73597e
RD
511}
512
513/*
514 * Look up a completion event file by FD. If lookup is successful,
515 * takes a ref to the event file struct that it returns; if
516 * unsuccessful, returns NULL.
517 */
518struct ib_uverbs_event_file *ib_uverbs_lookup_comp_file(int fd)
519{
520 struct ib_uverbs_event_file *ev_file = NULL;
521 struct file *filp;
522
523 filp = fget(fd);
524 if (!filp)
525 return NULL;
526
527 if (filp->f_op != &uverbs_event_fops)
528 goto out;
529
530 ev_file = filp->private_data;
531 if (ev_file->is_async) {
532 ev_file = NULL;
533 goto out;
534 }
535
536 kref_get(&ev_file->ref);
537
538out:
539 fput(filp);
540 return ev_file;
bc38a6ab
RD
541}
542
543static ssize_t ib_uverbs_write(struct file *filp, const char __user *buf,
544 size_t count, loff_t *pos)
545{
546 struct ib_uverbs_file *file = filp->private_data;
547 struct ib_uverbs_cmd_hdr hdr;
548
549 if (count < sizeof hdr)
550 return -EINVAL;
551
552 if (copy_from_user(&hdr, buf, sizeof hdr))
553 return -EFAULT;
554
555 if (hdr.in_words * 4 != count)
556 return -EINVAL;
557
63c47c28
RD
558 if (hdr.command < 0 ||
559 hdr.command >= ARRAY_SIZE(uverbs_cmd_table) ||
b1b8afb8 560 !uverbs_cmd_table[hdr.command])
bc38a6ab
RD
561 return -EINVAL;
562
6b73597e 563 if (!file->ucontext &&
bc38a6ab
RD
564 hdr.command != IB_USER_VERBS_CMD_GET_CONTEXT)
565 return -EINVAL;
566
b1b8afb8
JM
567 if (!(file->device->ib_dev->uverbs_cmd_mask & (1ull << hdr.command)))
568 return -ENOSYS;
569
bc38a6ab
RD
570 return uverbs_cmd_table[hdr.command](file, buf + sizeof hdr,
571 hdr.in_words * 4, hdr.out_words * 4);
572}
573
574static int ib_uverbs_mmap(struct file *filp, struct vm_area_struct *vma)
575{
576 struct ib_uverbs_file *file = filp->private_data;
577
578 if (!file->ucontext)
579 return -ENODEV;
580 else
581 return file->device->ib_dev->mmap(file->ucontext, vma);
582}
583
5b2d281a
RD
584/*
585 * ib_uverbs_open() does not need the BKL:
586 *
2a72f212 587 * - the ib_uverbs_device structures are properly reference counted and
5b2d281a
RD
588 * everything else is purely local to the file being created, so
589 * races against other open calls are not a problem;
590 * - there is no ioctl method to race against;
2a72f212
AC
591 * - the open method will either immediately run -ENXIO, or all
592 * required initialization will be done.
5b2d281a 593 */
bc38a6ab
RD
594static int ib_uverbs_open(struct inode *inode, struct file *filp)
595{
70a30e16 596 struct ib_uverbs_device *dev;
bc38a6ab 597 struct ib_uverbs_file *file;
70a30e16 598 int ret;
bc38a6ab 599
2a72f212 600 dev = container_of(inode->i_cdev, struct ib_uverbs_device, cdev);
70a30e16
RD
601 if (dev)
602 kref_get(&dev->ref);
2a72f212 603 else
70a30e16
RD
604 return -ENXIO;
605
606 if (!try_module_get(dev->ib_dev->owner)) {
607 ret = -ENODEV;
608 goto err;
609 }
bc38a6ab 610
6b73597e 611 file = kmalloc(sizeof *file, GFP_KERNEL);
63c47c28 612 if (!file) {
70a30e16
RD
613 ret = -ENOMEM;
614 goto err_module;
63c47c28 615 }
bc38a6ab 616
70a30e16
RD
617 file->device = dev;
618 file->ucontext = NULL;
619 file->async_file = NULL;
bc38a6ab 620 kref_init(&file->ref);
95ed644f 621 mutex_init(&file->mutex);
bc38a6ab 622
bc38a6ab
RD
623 filp->private_data = file;
624
bc38a6ab 625 return 0;
70a30e16
RD
626
627err_module:
628 module_put(dev->ib_dev->owner);
629
630err:
631 kref_put(&dev->ref, ib_uverbs_release_dev);
70a30e16 632 return ret;
bc38a6ab
RD
633}
634
635static int ib_uverbs_close(struct inode *inode, struct file *filp)
636{
637 struct ib_uverbs_file *file = filp->private_data;
bc38a6ab 638
70a30e16
RD
639 ib_uverbs_cleanup_ucontext(file, file->ucontext);
640
641 if (file->async_file)
642 kref_put(&file->async_file->ref, ib_uverbs_release_event_file);
bc38a6ab 643
bc38a6ab
RD
644 kref_put(&file->ref, ib_uverbs_release_file);
645
646 return 0;
647}
648
2b8693c0 649static const struct file_operations uverbs_fops = {
9afed76d
AC
650 .owner = THIS_MODULE,
651 .write = ib_uverbs_write,
652 .open = ib_uverbs_open,
bc38a6ab
RD
653 .release = ib_uverbs_close
654};
655
2b8693c0 656static const struct file_operations uverbs_mmap_fops = {
9afed76d
AC
657 .owner = THIS_MODULE,
658 .write = ib_uverbs_write,
bc38a6ab 659 .mmap = ib_uverbs_mmap,
9afed76d 660 .open = ib_uverbs_open,
bc38a6ab
RD
661 .release = ib_uverbs_close
662};
663
664static struct ib_client uverbs_client = {
665 .name = "uverbs",
666 .add = ib_uverbs_add_one,
667 .remove = ib_uverbs_remove_one
668};
669
f4e91eb4
TJ
670static ssize_t show_ibdev(struct device *device, struct device_attribute *attr,
671 char *buf)
bc38a6ab 672{
f4e91eb4 673 struct ib_uverbs_device *dev = dev_get_drvdata(device);
70a30e16
RD
674
675 if (!dev)
676 return -ENODEV;
bc38a6ab
RD
677
678 return sprintf(buf, "%s\n", dev->ib_dev->name);
679}
f4e91eb4 680static DEVICE_ATTR(ibdev, S_IRUGO, show_ibdev, NULL);
bc38a6ab 681
f4e91eb4
TJ
682static ssize_t show_dev_abi_version(struct device *device,
683 struct device_attribute *attr, char *buf)
274c0891 684{
f4e91eb4 685 struct ib_uverbs_device *dev = dev_get_drvdata(device);
70a30e16
RD
686
687 if (!dev)
688 return -ENODEV;
274c0891
RD
689
690 return sprintf(buf, "%d\n", dev->ib_dev->uverbs_abi_ver);
691}
f4e91eb4 692static DEVICE_ATTR(abi_version, S_IRUGO, show_dev_abi_version, NULL);
274c0891 693
28812fe1
AK
694static ssize_t show_abi_version(struct class *class,
695 struct class_attribute *attr,
696 char *buf)
bc38a6ab
RD
697{
698 return sprintf(buf, "%d\n", IB_USER_VERBS_ABI_VERSION);
699}
700static CLASS_ATTR(abi_version, S_IRUGO, show_abi_version, NULL);
701
6d6a0e71
AC
702static dev_t overflow_maj;
703static DECLARE_BITMAP(overflow_map, IB_UVERBS_MAX_DEVICES);
704
705/*
706 * If we have more than IB_UVERBS_MAX_DEVICES, dynamically overflow by
707 * requesting a new major number and doubling the number of max devices we
708 * support. It's stupid, but simple.
709 */
710static int find_overflow_devnum(void)
711{
712 int ret;
713
714 if (!overflow_maj) {
715 ret = alloc_chrdev_region(&overflow_maj, 0, IB_UVERBS_MAX_DEVICES,
716 "infiniband_verbs");
717 if (ret) {
718 printk(KERN_ERR "user_verbs: couldn't register dynamic device number\n");
719 return ret;
720 }
721 }
722
723 ret = find_first_zero_bit(overflow_map, IB_UVERBS_MAX_DEVICES);
724 if (ret >= IB_UVERBS_MAX_DEVICES)
725 return -1;
726
727 return ret;
728}
729
bc38a6ab
RD
730static void ib_uverbs_add_one(struct ib_device *device)
731{
38707980 732 int devnum;
ddbd6883 733 dev_t base;
bc38a6ab
RD
734 struct ib_uverbs_device *uverbs_dev;
735
736 if (!device->alloc_ucontext)
737 return;
738
de6eb66b 739 uverbs_dev = kzalloc(sizeof *uverbs_dev, GFP_KERNEL);
bc38a6ab
RD
740 if (!uverbs_dev)
741 return;
742
70a30e16 743 kref_init(&uverbs_dev->ref);
fd60ae40 744 init_completion(&uverbs_dev->comp);
70a30e16 745
bc38a6ab 746 spin_lock(&map_lock);
38707980
AC
747 devnum = find_first_zero_bit(dev_map, IB_UVERBS_MAX_DEVICES);
748 if (devnum >= IB_UVERBS_MAX_DEVICES) {
bc38a6ab 749 spin_unlock(&map_lock);
6d6a0e71
AC
750 devnum = find_overflow_devnum();
751 if (devnum < 0)
752 goto err;
753
754 spin_lock(&map_lock);
755 uverbs_dev->devnum = devnum + IB_UVERBS_MAX_DEVICES;
756 base = devnum + overflow_maj;
757 set_bit(devnum, overflow_map);
758 } else {
759 uverbs_dev->devnum = devnum;
760 base = devnum + IB_UVERBS_BASE_DEV;
761 set_bit(devnum, dev_map);
bc38a6ab 762 }
bc38a6ab
RD
763 spin_unlock(&map_lock);
764
6b73597e 765 uverbs_dev->ib_dev = device;
f4fd0b22 766 uverbs_dev->num_comp_vectors = device->num_comp_vectors;
bc38a6ab 767
055422dd
AC
768 cdev_init(&uverbs_dev->cdev, NULL);
769 uverbs_dev->cdev.owner = THIS_MODULE;
770 uverbs_dev->cdev.ops = device->mmap ? &uverbs_mmap_fops : &uverbs_fops;
771 kobject_set_name(&uverbs_dev->cdev.kobj, "uverbs%d", uverbs_dev->devnum);
ddbd6883 772 if (cdev_add(&uverbs_dev->cdev, base, 1))
70a30e16 773 goto err_cdev;
bc38a6ab 774
91bd418f 775 uverbs_dev->dev = device_create(uverbs_class, device->dma_device,
055422dd 776 uverbs_dev->cdev.dev, uverbs_dev,
91bd418f 777 "uverbs%d", uverbs_dev->devnum);
f4e91eb4 778 if (IS_ERR(uverbs_dev->dev))
bc38a6ab
RD
779 goto err_cdev;
780
f4e91eb4 781 if (device_create_file(uverbs_dev->dev, &dev_attr_ibdev))
bc38a6ab 782 goto err_class;
f4e91eb4 783 if (device_create_file(uverbs_dev->dev, &dev_attr_abi_version))
274c0891 784 goto err_class;
bc38a6ab
RD
785
786 ib_set_client_data(device, &uverbs_client, uverbs_dev);
787
788 return;
789
790err_class:
055422dd 791 device_destroy(uverbs_class, uverbs_dev->cdev.dev);
bc38a6ab
RD
792
793err_cdev:
055422dd 794 cdev_del(&uverbs_dev->cdev);
6d6a0e71
AC
795 if (uverbs_dev->devnum < IB_UVERBS_MAX_DEVICES)
796 clear_bit(devnum, dev_map);
797 else
798 clear_bit(devnum, overflow_map);
bc38a6ab
RD
799
800err:
70a30e16 801 kref_put(&uverbs_dev->ref, ib_uverbs_release_dev);
fd60ae40
JM
802 wait_for_completion(&uverbs_dev->comp);
803 kfree(uverbs_dev);
bc38a6ab
RD
804 return;
805}
806
807static void ib_uverbs_remove_one(struct ib_device *device)
808{
809 struct ib_uverbs_device *uverbs_dev = ib_get_client_data(device, &uverbs_client);
810
811 if (!uverbs_dev)
812 return;
813
f4e91eb4 814 dev_set_drvdata(uverbs_dev->dev, NULL);
055422dd
AC
815 device_destroy(uverbs_class, uverbs_dev->cdev.dev);
816 cdev_del(&uverbs_dev->cdev);
70a30e16 817
6d6a0e71
AC
818 if (uverbs_dev->devnum < IB_UVERBS_MAX_DEVICES)
819 clear_bit(uverbs_dev->devnum, dev_map);
820 else
821 clear_bit(uverbs_dev->devnum - IB_UVERBS_MAX_DEVICES, overflow_map);
fd60ae40 822
70a30e16 823 kref_put(&uverbs_dev->ref, ib_uverbs_release_dev);
fd60ae40
JM
824 wait_for_completion(&uverbs_dev->comp);
825 kfree(uverbs_dev);
bc38a6ab
RD
826}
827
bc38a6ab
RD
828static int __init ib_uverbs_init(void)
829{
830 int ret;
831
bc38a6ab
RD
832 ret = register_chrdev_region(IB_UVERBS_BASE_DEV, IB_UVERBS_MAX_DEVICES,
833 "infiniband_verbs");
834 if (ret) {
835 printk(KERN_ERR "user_verbs: couldn't register device number\n");
836 goto out;
837 }
838
70a30e16
RD
839 uverbs_class = class_create(THIS_MODULE, "infiniband_verbs");
840 if (IS_ERR(uverbs_class)) {
841 ret = PTR_ERR(uverbs_class);
bc38a6ab
RD
842 printk(KERN_ERR "user_verbs: couldn't create class infiniband_verbs\n");
843 goto out_chrdev;
844 }
845
70a30e16 846 ret = class_create_file(uverbs_class, &class_attr_abi_version);
bc38a6ab
RD
847 if (ret) {
848 printk(KERN_ERR "user_verbs: couldn't create abi_version attribute\n");
849 goto out_class;
850 }
851
bc38a6ab
RD
852 ret = ib_register_client(&uverbs_client);
853 if (ret) {
854 printk(KERN_ERR "user_verbs: couldn't register client\n");
a265e558 855 goto out_class;
bc38a6ab
RD
856 }
857
858 return 0;
859
bc38a6ab 860out_class:
70a30e16 861 class_destroy(uverbs_class);
bc38a6ab
RD
862
863out_chrdev:
864 unregister_chrdev_region(IB_UVERBS_BASE_DEV, IB_UVERBS_MAX_DEVICES);
865
866out:
867 return ret;
868}
869
870static void __exit ib_uverbs_cleanup(void)
871{
872 ib_unregister_client(&uverbs_client);
70a30e16 873 class_destroy(uverbs_class);
bc38a6ab 874 unregister_chrdev_region(IB_UVERBS_BASE_DEV, IB_UVERBS_MAX_DEVICES);
6d6a0e71
AC
875 if (overflow_maj)
876 unregister_chrdev_region(overflow_maj, IB_UVERBS_MAX_DEVICES);
5d7edb3c
RD
877 idr_destroy(&ib_uverbs_pd_idr);
878 idr_destroy(&ib_uverbs_mr_idr);
879 idr_destroy(&ib_uverbs_mw_idr);
880 idr_destroy(&ib_uverbs_ah_idr);
881 idr_destroy(&ib_uverbs_cq_idr);
882 idr_destroy(&ib_uverbs_qp_idr);
883 idr_destroy(&ib_uverbs_srq_idr);
bc38a6ab
RD
884}
885
886module_init(ib_uverbs_init);
887module_exit(ib_uverbs_cleanup);