aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/infiniband/core/uverbs_main.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/infiniband/core/uverbs_main.c')
-rw-r--r--drivers/infiniband/core/uverbs_main.c503
1 files changed, 321 insertions, 182 deletions
diff --git a/drivers/infiniband/core/uverbs_main.c b/drivers/infiniband/core/uverbs_main.c
index 12511808de2..0eb38f479b3 100644
--- a/drivers/infiniband/core/uverbs_main.c
+++ b/drivers/infiniband/core/uverbs_main.c
@@ -3,6 +3,7 @@
3 * Copyright (c) 2005 Cisco Systems. All rights reserved. 3 * Copyright (c) 2005 Cisco Systems. All rights reserved.
4 * Copyright (c) 2005 Mellanox Technologies. All rights reserved. 4 * Copyright (c) 2005 Mellanox Technologies. All rights reserved.
5 * Copyright (c) 2005 Voltaire, Inc. All rights reserved. 5 * Copyright (c) 2005 Voltaire, Inc. All rights reserved.
6 * Copyright (c) 2005 PathScale, Inc. All rights reserved.
6 * 7 *
7 * This software is available to you under a choice of one of two 8 * 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 * licenses. You may choose to be licensed under the terms of the GNU
@@ -43,6 +44,7 @@
43#include <linux/poll.h> 44#include <linux/poll.h>
44#include <linux/file.h> 45#include <linux/file.h>
45#include <linux/mount.h> 46#include <linux/mount.h>
47#include <linux/cdev.h>
46 48
47#include <asm/uaccess.h> 49#include <asm/uaccess.h>
48 50
@@ -62,6 +64,8 @@ enum {
62 64
63#define IB_UVERBS_BASE_DEV MKDEV(IB_UVERBS_MAJOR, IB_UVERBS_BASE_MINOR) 65#define IB_UVERBS_BASE_DEV MKDEV(IB_UVERBS_MAJOR, IB_UVERBS_BASE_MINOR)
64 66
67static struct class *uverbs_class;
68
65DECLARE_MUTEX(ib_uverbs_idr_mutex); 69DECLARE_MUTEX(ib_uverbs_idr_mutex);
66DEFINE_IDR(ib_uverbs_pd_idr); 70DEFINE_IDR(ib_uverbs_pd_idr);
67DEFINE_IDR(ib_uverbs_mr_idr); 71DEFINE_IDR(ib_uverbs_mr_idr);
@@ -72,31 +76,37 @@ DEFINE_IDR(ib_uverbs_qp_idr);
72DEFINE_IDR(ib_uverbs_srq_idr); 76DEFINE_IDR(ib_uverbs_srq_idr);
73 77
74static spinlock_t map_lock; 78static spinlock_t map_lock;
79static struct ib_uverbs_device *dev_table[IB_UVERBS_MAX_DEVICES];
75static DECLARE_BITMAP(dev_map, IB_UVERBS_MAX_DEVICES); 80static DECLARE_BITMAP(dev_map, IB_UVERBS_MAX_DEVICES);
76 81
77static ssize_t (*uverbs_cmd_table[])(struct ib_uverbs_file *file, 82static ssize_t (*uverbs_cmd_table[])(struct ib_uverbs_file *file,
78 const char __user *buf, int in_len, 83 const char __user *buf, int in_len,
79 int out_len) = { 84 int out_len) = {
80 [IB_USER_VERBS_CMD_QUERY_PARAMS] = ib_uverbs_query_params, 85 [IB_USER_VERBS_CMD_GET_CONTEXT] = ib_uverbs_get_context,
81 [IB_USER_VERBS_CMD_GET_CONTEXT] = ib_uverbs_get_context, 86 [IB_USER_VERBS_CMD_QUERY_DEVICE] = ib_uverbs_query_device,
82 [IB_USER_VERBS_CMD_QUERY_DEVICE] = ib_uverbs_query_device, 87 [IB_USER_VERBS_CMD_QUERY_PORT] = ib_uverbs_query_port,
83 [IB_USER_VERBS_CMD_QUERY_PORT] = ib_uverbs_query_port, 88 [IB_USER_VERBS_CMD_ALLOC_PD] = ib_uverbs_alloc_pd,
84 [IB_USER_VERBS_CMD_QUERY_GID] = ib_uverbs_query_gid, 89 [IB_USER_VERBS_CMD_DEALLOC_PD] = ib_uverbs_dealloc_pd,
85 [IB_USER_VERBS_CMD_QUERY_PKEY] = ib_uverbs_query_pkey, 90 [IB_USER_VERBS_CMD_REG_MR] = ib_uverbs_reg_mr,
86 [IB_USER_VERBS_CMD_ALLOC_PD] = ib_uverbs_alloc_pd, 91 [IB_USER_VERBS_CMD_DEREG_MR] = ib_uverbs_dereg_mr,
87 [IB_USER_VERBS_CMD_DEALLOC_PD] = ib_uverbs_dealloc_pd, 92 [IB_USER_VERBS_CMD_CREATE_COMP_CHANNEL] = ib_uverbs_create_comp_channel,
88 [IB_USER_VERBS_CMD_REG_MR] = ib_uverbs_reg_mr, 93 [IB_USER_VERBS_CMD_CREATE_CQ] = ib_uverbs_create_cq,
89 [IB_USER_VERBS_CMD_DEREG_MR] = ib_uverbs_dereg_mr, 94 [IB_USER_VERBS_CMD_POLL_CQ] = ib_uverbs_poll_cq,
90 [IB_USER_VERBS_CMD_CREATE_CQ] = ib_uverbs_create_cq, 95 [IB_USER_VERBS_CMD_REQ_NOTIFY_CQ] = ib_uverbs_req_notify_cq,
91 [IB_USER_VERBS_CMD_DESTROY_CQ] = ib_uverbs_destroy_cq, 96 [IB_USER_VERBS_CMD_DESTROY_CQ] = ib_uverbs_destroy_cq,
92 [IB_USER_VERBS_CMD_CREATE_QP] = ib_uverbs_create_qp, 97 [IB_USER_VERBS_CMD_CREATE_QP] = ib_uverbs_create_qp,
93 [IB_USER_VERBS_CMD_MODIFY_QP] = ib_uverbs_modify_qp, 98 [IB_USER_VERBS_CMD_MODIFY_QP] = ib_uverbs_modify_qp,
94 [IB_USER_VERBS_CMD_DESTROY_QP] = ib_uverbs_destroy_qp, 99 [IB_USER_VERBS_CMD_DESTROY_QP] = ib_uverbs_destroy_qp,
95 [IB_USER_VERBS_CMD_ATTACH_MCAST] = ib_uverbs_attach_mcast, 100 [IB_USER_VERBS_CMD_POST_SEND] = ib_uverbs_post_send,
96 [IB_USER_VERBS_CMD_DETACH_MCAST] = ib_uverbs_detach_mcast, 101 [IB_USER_VERBS_CMD_POST_RECV] = ib_uverbs_post_recv,
97 [IB_USER_VERBS_CMD_CREATE_SRQ] = ib_uverbs_create_srq, 102 [IB_USER_VERBS_CMD_POST_SRQ_RECV] = ib_uverbs_post_srq_recv,
98 [IB_USER_VERBS_CMD_MODIFY_SRQ] = ib_uverbs_modify_srq, 103 [IB_USER_VERBS_CMD_CREATE_AH] = ib_uverbs_create_ah,
99 [IB_USER_VERBS_CMD_DESTROY_SRQ] = ib_uverbs_destroy_srq, 104 [IB_USER_VERBS_CMD_DESTROY_AH] = ib_uverbs_destroy_ah,
105 [IB_USER_VERBS_CMD_ATTACH_MCAST] = ib_uverbs_attach_mcast,
106 [IB_USER_VERBS_CMD_DETACH_MCAST] = ib_uverbs_detach_mcast,
107 [IB_USER_VERBS_CMD_CREATE_SRQ] = ib_uverbs_create_srq,
108 [IB_USER_VERBS_CMD_MODIFY_SRQ] = ib_uverbs_modify_srq,
109 [IB_USER_VERBS_CMD_DESTROY_SRQ] = ib_uverbs_destroy_srq,
100}; 110};
101 111
102static struct vfsmount *uverbs_event_mnt; 112static struct vfsmount *uverbs_event_mnt;
@@ -104,7 +114,54 @@ static struct vfsmount *uverbs_event_mnt;
104static void ib_uverbs_add_one(struct ib_device *device); 114static void ib_uverbs_add_one(struct ib_device *device);
105static void ib_uverbs_remove_one(struct ib_device *device); 115static void ib_uverbs_remove_one(struct ib_device *device);
106 116
107static int ib_dealloc_ucontext(struct ib_ucontext *context) 117static void ib_uverbs_release_dev(struct kref *ref)
118{
119 struct ib_uverbs_device *dev =
120 container_of(ref, struct ib_uverbs_device, ref);
121
122 kfree(dev);
123}
124
125void ib_uverbs_release_ucq(struct ib_uverbs_file *file,
126 struct ib_uverbs_event_file *ev_file,
127 struct ib_ucq_object *uobj)
128{
129 struct ib_uverbs_event *evt, *tmp;
130
131 if (ev_file) {
132 spin_lock_irq(&ev_file->lock);
133 list_for_each_entry_safe(evt, tmp, &uobj->comp_list, obj_list) {
134 list_del(&evt->list);
135 kfree(evt);
136 }
137 spin_unlock_irq(&ev_file->lock);
138
139 kref_put(&ev_file->ref, ib_uverbs_release_event_file);
140 }
141
142 spin_lock_irq(&file->async_file->lock);
143 list_for_each_entry_safe(evt, tmp, &uobj->async_list, obj_list) {
144 list_del(&evt->list);
145 kfree(evt);
146 }
147 spin_unlock_irq(&file->async_file->lock);
148}
149
150void ib_uverbs_release_uevent(struct ib_uverbs_file *file,
151 struct ib_uevent_object *uobj)
152{
153 struct ib_uverbs_event *evt, *tmp;
154
155 spin_lock_irq(&file->async_file->lock);
156 list_for_each_entry_safe(evt, tmp, &uobj->event_list, obj_list) {
157 list_del(&evt->list);
158 kfree(evt);
159 }
160 spin_unlock_irq(&file->async_file->lock);
161}
162
163static int ib_uverbs_cleanup_ucontext(struct ib_uverbs_file *file,
164 struct ib_ucontext *context)
108{ 165{
109 struct ib_uobject *uobj, *tmp; 166 struct ib_uobject *uobj, *tmp;
110 167
@@ -113,30 +170,46 @@ static int ib_dealloc_ucontext(struct ib_ucontext *context)
113 170
114 down(&ib_uverbs_idr_mutex); 171 down(&ib_uverbs_idr_mutex);
115 172
116 /* XXX Free AHs */ 173 list_for_each_entry_safe(uobj, tmp, &context->ah_list, list) {
174 struct ib_ah *ah = idr_find(&ib_uverbs_ah_idr, uobj->id);
175 idr_remove(&ib_uverbs_ah_idr, uobj->id);
176 ib_destroy_ah(ah);
177 list_del(&uobj->list);
178 kfree(uobj);
179 }
117 180
118 list_for_each_entry_safe(uobj, tmp, &context->qp_list, list) { 181 list_for_each_entry_safe(uobj, tmp, &context->qp_list, list) {
119 struct ib_qp *qp = idr_find(&ib_uverbs_qp_idr, uobj->id); 182 struct ib_qp *qp = idr_find(&ib_uverbs_qp_idr, uobj->id);
183 struct ib_uevent_object *uevent =
184 container_of(uobj, struct ib_uevent_object, uobject);
120 idr_remove(&ib_uverbs_qp_idr, uobj->id); 185 idr_remove(&ib_uverbs_qp_idr, uobj->id);
121 ib_destroy_qp(qp); 186 ib_destroy_qp(qp);
122 list_del(&uobj->list); 187 list_del(&uobj->list);
123 kfree(container_of(uobj, struct ib_uevent_object, uobject)); 188 ib_uverbs_release_uevent(file, uevent);
189 kfree(uevent);
124 } 190 }
125 191
126 list_for_each_entry_safe(uobj, tmp, &context->cq_list, list) { 192 list_for_each_entry_safe(uobj, tmp, &context->cq_list, list) {
127 struct ib_cq *cq = idr_find(&ib_uverbs_cq_idr, uobj->id); 193 struct ib_cq *cq = idr_find(&ib_uverbs_cq_idr, uobj->id);
194 struct ib_uverbs_event_file *ev_file = cq->cq_context;
195 struct ib_ucq_object *ucq =
196 container_of(uobj, struct ib_ucq_object, uobject);
128 idr_remove(&ib_uverbs_cq_idr, uobj->id); 197 idr_remove(&ib_uverbs_cq_idr, uobj->id);
129 ib_destroy_cq(cq); 198 ib_destroy_cq(cq);
130 list_del(&uobj->list); 199 list_del(&uobj->list);
131 kfree(container_of(uobj, struct ib_ucq_object, uobject)); 200 ib_uverbs_release_ucq(file, ev_file, ucq);
201 kfree(ucq);
132 } 202 }
133 203
134 list_for_each_entry_safe(uobj, tmp, &context->srq_list, list) { 204 list_for_each_entry_safe(uobj, tmp, &context->srq_list, list) {
135 struct ib_srq *srq = idr_find(&ib_uverbs_srq_idr, uobj->id); 205 struct ib_srq *srq = idr_find(&ib_uverbs_srq_idr, uobj->id);
206 struct ib_uevent_object *uevent =
207 container_of(uobj, struct ib_uevent_object, uobject);
136 idr_remove(&ib_uverbs_srq_idr, uobj->id); 208 idr_remove(&ib_uverbs_srq_idr, uobj->id);
137 ib_destroy_srq(srq); 209 ib_destroy_srq(srq);
138 list_del(&uobj->list); 210 list_del(&uobj->list);
139 kfree(container_of(uobj, struct ib_uevent_object, uobject)); 211 ib_uverbs_release_uevent(file, uevent);
212 kfree(uevent);
140 } 213 }
141 214
142 /* XXX Free MWs */ 215 /* XXX Free MWs */
@@ -175,6 +248,8 @@ static void ib_uverbs_release_file(struct kref *ref)
175 container_of(ref, struct ib_uverbs_file, ref); 248 container_of(ref, struct ib_uverbs_file, ref);
176 249
177 module_put(file->device->ib_dev->owner); 250 module_put(file->device->ib_dev->owner);
251 kref_put(&file->device->ref, ib_uverbs_release_dev);
252
178 kfree(file); 253 kfree(file);
179} 254}
180 255
@@ -188,25 +263,19 @@ static ssize_t ib_uverbs_event_read(struct file *filp, char __user *buf,
188 263
189 spin_lock_irq(&file->lock); 264 spin_lock_irq(&file->lock);
190 265
191 while (list_empty(&file->event_list) && file->fd >= 0) { 266 while (list_empty(&file->event_list)) {
192 spin_unlock_irq(&file->lock); 267 spin_unlock_irq(&file->lock);
193 268
194 if (filp->f_flags & O_NONBLOCK) 269 if (filp->f_flags & O_NONBLOCK)
195 return -EAGAIN; 270 return -EAGAIN;
196 271
197 if (wait_event_interruptible(file->poll_wait, 272 if (wait_event_interruptible(file->poll_wait,
198 !list_empty(&file->event_list) || 273 !list_empty(&file->event_list)))
199 file->fd < 0))
200 return -ERESTARTSYS; 274 return -ERESTARTSYS;
201 275
202 spin_lock_irq(&file->lock); 276 spin_lock_irq(&file->lock);
203 } 277 }
204 278
205 if (file->fd < 0) {
206 spin_unlock_irq(&file->lock);
207 return -ENODEV;
208 }
209
210 event = list_entry(file->event_list.next, struct ib_uverbs_event, list); 279 event = list_entry(file->event_list.next, struct ib_uverbs_event, list);
211 280
212 if (file->is_async) 281 if (file->is_async)
@@ -248,26 +317,19 @@ static unsigned int ib_uverbs_event_poll(struct file *filp,
248 poll_wait(filp, &file->poll_wait, wait); 317 poll_wait(filp, &file->poll_wait, wait);
249 318
250 spin_lock_irq(&file->lock); 319 spin_lock_irq(&file->lock);
251 if (file->fd < 0) 320 if (!list_empty(&file->event_list))
252 pollflags = POLLERR;
253 else if (!list_empty(&file->event_list))
254 pollflags = POLLIN | POLLRDNORM; 321 pollflags = POLLIN | POLLRDNORM;
255 spin_unlock_irq(&file->lock); 322 spin_unlock_irq(&file->lock);
256 323
257 return pollflags; 324 return pollflags;
258} 325}
259 326
260static void ib_uverbs_event_release(struct ib_uverbs_event_file *file) 327void ib_uverbs_release_event_file(struct kref *ref)
261{ 328{
262 struct ib_uverbs_event *entry, *tmp; 329 struct ib_uverbs_event_file *file =
330 container_of(ref, struct ib_uverbs_event_file, ref);
263 331
264 spin_lock_irq(&file->lock); 332 kfree(file);
265 if (file->fd != -1) {
266 file->fd = -1;
267 list_for_each_entry_safe(entry, tmp, &file->event_list, list)
268 kfree(entry);
269 }
270 spin_unlock_irq(&file->lock);
271} 333}
272 334
273static int ib_uverbs_event_fasync(int fd, struct file *filp, int on) 335static int ib_uverbs_event_fasync(int fd, struct file *filp, int on)
@@ -280,21 +342,30 @@ static int ib_uverbs_event_fasync(int fd, struct file *filp, int on)
280static int ib_uverbs_event_close(struct inode *inode, struct file *filp) 342static int ib_uverbs_event_close(struct inode *inode, struct file *filp)
281{ 343{
282 struct ib_uverbs_event_file *file = filp->private_data; 344 struct ib_uverbs_event_file *file = filp->private_data;
345 struct ib_uverbs_event *entry, *tmp;
346
347 spin_lock_irq(&file->lock);
348 file->file = NULL;
349 list_for_each_entry_safe(entry, tmp, &file->event_list, list) {
350 if (entry->counter)
351 list_del(&entry->obj_list);
352 kfree(entry);
353 }
354 spin_unlock_irq(&file->lock);
283 355
284 ib_uverbs_event_release(file);
285 ib_uverbs_event_fasync(-1, filp, 0); 356 ib_uverbs_event_fasync(-1, filp, 0);
286 kref_put(&file->uverbs_file->ref, ib_uverbs_release_file); 357
358 if (file->is_async) {
359 ib_unregister_event_handler(&file->uverbs_file->event_handler);
360 kref_put(&file->uverbs_file->ref, ib_uverbs_release_file);
361 }
362 kref_put(&file->ref, ib_uverbs_release_event_file);
287 363
288 return 0; 364 return 0;
289} 365}
290 366
291static struct file_operations uverbs_event_fops = { 367static struct file_operations uverbs_event_fops = {
292 /* 368 .owner = THIS_MODULE,
293 * No .owner field since we artificially create event files,
294 * so there is no increment to the module reference count in
295 * the open path. All event files come from a uverbs command
296 * file, which already takes a module reference, so this is OK.
297 */
298 .read = ib_uverbs_event_read, 369 .read = ib_uverbs_event_read,
299 .poll = ib_uverbs_event_poll, 370 .poll = ib_uverbs_event_poll,
300 .release = ib_uverbs_event_close, 371 .release = ib_uverbs_event_close,
@@ -303,27 +374,37 @@ static struct file_operations uverbs_event_fops = {
303 374
304void ib_uverbs_comp_handler(struct ib_cq *cq, void *cq_context) 375void ib_uverbs_comp_handler(struct ib_cq *cq, void *cq_context)
305{ 376{
306 struct ib_uverbs_file *file = cq_context; 377 struct ib_uverbs_event_file *file = cq_context;
307 struct ib_ucq_object *uobj; 378 struct ib_ucq_object *uobj;
308 struct ib_uverbs_event *entry; 379 struct ib_uverbs_event *entry;
309 unsigned long flags; 380 unsigned long flags;
381
382 if (!file)
383 return;
384
385 spin_lock_irqsave(&file->lock, flags);
386 if (!file->file) {
387 spin_unlock_irqrestore(&file->lock, flags);
388 return;
389 }
310 390
311 entry = kmalloc(sizeof *entry, GFP_ATOMIC); 391 entry = kmalloc(sizeof *entry, GFP_ATOMIC);
312 if (!entry) 392 if (!entry) {
393 spin_unlock_irqrestore(&file->lock, flags);
313 return; 394 return;
395 }
314 396
315 uobj = container_of(cq->uobject, struct ib_ucq_object, uobject); 397 uobj = container_of(cq->uobject, struct ib_ucq_object, uobject);
316 398
317 entry->desc.comp.cq_handle = cq->uobject->user_handle; 399 entry->desc.comp.cq_handle = cq->uobject->user_handle;
318 entry->counter = &uobj->comp_events_reported; 400 entry->counter = &uobj->comp_events_reported;
319 401
320 spin_lock_irqsave(&file->comp_file[0].lock, flags); 402 list_add_tail(&entry->list, &file->event_list);
321 list_add_tail(&entry->list, &file->comp_file[0].event_list);
322 list_add_tail(&entry->obj_list, &uobj->comp_list); 403 list_add_tail(&entry->obj_list, &uobj->comp_list);
323 spin_unlock_irqrestore(&file->comp_file[0].lock, flags); 404 spin_unlock_irqrestore(&file->lock, flags);
324 405
325 wake_up_interruptible(&file->comp_file[0].poll_wait); 406 wake_up_interruptible(&file->poll_wait);
326 kill_fasync(&file->comp_file[0].async_queue, SIGIO, POLL_IN); 407 kill_fasync(&file->async_queue, SIGIO, POLL_IN);
327} 408}
328 409
329static void ib_uverbs_async_handler(struct ib_uverbs_file *file, 410static void ib_uverbs_async_handler(struct ib_uverbs_file *file,
@@ -334,32 +415,40 @@ static void ib_uverbs_async_handler(struct ib_uverbs_file *file,
334 struct ib_uverbs_event *entry; 415 struct ib_uverbs_event *entry;
335 unsigned long flags; 416 unsigned long flags;
336 417
418 spin_lock_irqsave(&file->async_file->lock, flags);
419 if (!file->async_file->file) {
420 spin_unlock_irqrestore(&file->async_file->lock, flags);
421 return;
422 }
423
337 entry = kmalloc(sizeof *entry, GFP_ATOMIC); 424 entry = kmalloc(sizeof *entry, GFP_ATOMIC);
338 if (!entry) 425 if (!entry) {
426 spin_unlock_irqrestore(&file->async_file->lock, flags);
339 return; 427 return;
428 }
340 429
341 entry->desc.async.element = element; 430 entry->desc.async.element = element;
342 entry->desc.async.event_type = event; 431 entry->desc.async.event_type = event;
343 entry->counter = counter; 432 entry->counter = counter;
344 433
345 spin_lock_irqsave(&file->async_file.lock, flags); 434 list_add_tail(&entry->list, &file->async_file->event_list);
346 list_add_tail(&entry->list, &file->async_file.event_list);
347 if (obj_list) 435 if (obj_list)
348 list_add_tail(&entry->obj_list, obj_list); 436 list_add_tail(&entry->obj_list, obj_list);
349 spin_unlock_irqrestore(&file->async_file.lock, flags); 437 spin_unlock_irqrestore(&file->async_file->lock, flags);
350 438
351 wake_up_interruptible(&file->async_file.poll_wait); 439 wake_up_interruptible(&file->async_file->poll_wait);
352 kill_fasync(&file->async_file.async_queue, SIGIO, POLL_IN); 440 kill_fasync(&file->async_file->async_queue, SIGIO, POLL_IN);
353} 441}
354 442
355void ib_uverbs_cq_event_handler(struct ib_event *event, void *context_ptr) 443void ib_uverbs_cq_event_handler(struct ib_event *event, void *context_ptr)
356{ 444{
445 struct ib_uverbs_event_file *ev_file = context_ptr;
357 struct ib_ucq_object *uobj; 446 struct ib_ucq_object *uobj;
358 447
359 uobj = container_of(event->element.cq->uobject, 448 uobj = container_of(event->element.cq->uobject,
360 struct ib_ucq_object, uobject); 449 struct ib_ucq_object, uobject);
361 450
362 ib_uverbs_async_handler(context_ptr, uobj->uobject.user_handle, 451 ib_uverbs_async_handler(ev_file->uverbs_file, uobj->uobject.user_handle,
363 event->event, &uobj->async_list, 452 event->event, &uobj->async_list,
364 &uobj->async_events_reported); 453 &uobj->async_events_reported);
365 454
@@ -389,8 +478,8 @@ void ib_uverbs_srq_event_handler(struct ib_event *event, void *context_ptr)
389 &uobj->events_reported); 478 &uobj->events_reported);
390} 479}
391 480
392static void ib_uverbs_event_handler(struct ib_event_handler *handler, 481void ib_uverbs_event_handler(struct ib_event_handler *handler,
393 struct ib_event *event) 482 struct ib_event *event)
394{ 483{
395 struct ib_uverbs_file *file = 484 struct ib_uverbs_file *file =
396 container_of(handler, struct ib_uverbs_file, event_handler); 485 container_of(handler, struct ib_uverbs_file, event_handler);
@@ -399,38 +488,90 @@ static void ib_uverbs_event_handler(struct ib_event_handler *handler,
399 NULL, NULL); 488 NULL, NULL);
400} 489}
401 490
402static int ib_uverbs_event_init(struct ib_uverbs_event_file *file, 491struct file *ib_uverbs_alloc_event_file(struct ib_uverbs_file *uverbs_file,
403 struct ib_uverbs_file *uverbs_file) 492 int is_async, int *fd)
404{ 493{
494 struct ib_uverbs_event_file *ev_file;
405 struct file *filp; 495 struct file *filp;
496 int ret;
406 497
407 spin_lock_init(&file->lock); 498 ev_file = kmalloc(sizeof *ev_file, GFP_KERNEL);
408 INIT_LIST_HEAD(&file->event_list); 499 if (!ev_file)
409 init_waitqueue_head(&file->poll_wait); 500 return ERR_PTR(-ENOMEM);
410 file->uverbs_file = uverbs_file; 501
411 file->async_queue = NULL; 502 kref_init(&ev_file->ref);
412 503 spin_lock_init(&ev_file->lock);
413 file->fd = get_unused_fd(); 504 INIT_LIST_HEAD(&ev_file->event_list);
414 if (file->fd < 0) 505 init_waitqueue_head(&ev_file->poll_wait);
415 return file->fd; 506 ev_file->uverbs_file = uverbs_file;
507 ev_file->async_queue = NULL;
508 ev_file->is_async = is_async;
509
510 *fd = get_unused_fd();
511 if (*fd < 0) {
512 ret = *fd;
513 goto err;
514 }
416 515
417 filp = get_empty_filp(); 516 filp = get_empty_filp();
418 if (!filp) { 517 if (!filp) {
419 put_unused_fd(file->fd); 518 ret = -ENFILE;
420 return -ENFILE; 519 goto err_fd;
421 } 520 }
422 521
423 filp->f_op = &uverbs_event_fops; 522 ev_file->file = filp;
523
524 /*
525 * fops_get() can't fail here, because we're coming from a
526 * system call on a uverbs file, which will already have a
527 * module reference.
528 */
529 filp->f_op = fops_get(&uverbs_event_fops);
424 filp->f_vfsmnt = mntget(uverbs_event_mnt); 530 filp->f_vfsmnt = mntget(uverbs_event_mnt);
425 filp->f_dentry = dget(uverbs_event_mnt->mnt_root); 531 filp->f_dentry = dget(uverbs_event_mnt->mnt_root);
426 filp->f_mapping = filp->f_dentry->d_inode->i_mapping; 532 filp->f_mapping = filp->f_dentry->d_inode->i_mapping;
427 filp->f_flags = O_RDONLY; 533 filp->f_flags = O_RDONLY;
428 filp->f_mode = FMODE_READ; 534 filp->f_mode = FMODE_READ;
429 filp->private_data = file; 535 filp->private_data = ev_file;
430 536
431 fd_install(file->fd, filp); 537 return filp;
432 538
433 return 0; 539err_fd:
540 put_unused_fd(*fd);
541
542err:
543 kfree(ev_file);
544 return ERR_PTR(ret);
545}
546
547/*
548 * Look up a completion event file by FD. If lookup is successful,
549 * takes a ref to the event file struct that it returns; if
550 * unsuccessful, returns NULL.
551 */
552struct ib_uverbs_event_file *ib_uverbs_lookup_comp_file(int fd)
553{
554 struct ib_uverbs_event_file *ev_file = NULL;
555 struct file *filp;
556
557 filp = fget(fd);
558 if (!filp)
559 return NULL;
560
561 if (filp->f_op != &uverbs_event_fops)
562 goto out;
563
564 ev_file = filp->private_data;
565 if (ev_file->is_async) {
566 ev_file = NULL;
567 goto out;
568 }
569
570 kref_get(&ev_file->ref);
571
572out:
573 fput(filp);
574 return ev_file;
434} 575}
435 576
436static ssize_t ib_uverbs_write(struct file *filp, const char __user *buf, 577static ssize_t ib_uverbs_write(struct file *filp, const char __user *buf,
@@ -450,11 +591,11 @@ static ssize_t ib_uverbs_write(struct file *filp, const char __user *buf,
450 591
451 if (hdr.command < 0 || 592 if (hdr.command < 0 ||
452 hdr.command >= ARRAY_SIZE(uverbs_cmd_table) || 593 hdr.command >= ARRAY_SIZE(uverbs_cmd_table) ||
453 !uverbs_cmd_table[hdr.command]) 594 !uverbs_cmd_table[hdr.command] ||
595 !(file->device->ib_dev->uverbs_cmd_mask & (1ull << hdr.command)))
454 return -EINVAL; 596 return -EINVAL;
455 597
456 if (!file->ucontext && 598 if (!file->ucontext &&
457 hdr.command != IB_USER_VERBS_CMD_QUERY_PARAMS &&
458 hdr.command != IB_USER_VERBS_CMD_GET_CONTEXT) 599 hdr.command != IB_USER_VERBS_CMD_GET_CONTEXT)
459 return -EINVAL; 600 return -EINVAL;
460 601
@@ -474,84 +615,57 @@ static int ib_uverbs_mmap(struct file *filp, struct vm_area_struct *vma)
474 615
475static int ib_uverbs_open(struct inode *inode, struct file *filp) 616static int ib_uverbs_open(struct inode *inode, struct file *filp)
476{ 617{
477 struct ib_uverbs_device *dev = 618 struct ib_uverbs_device *dev;
478 container_of(inode->i_cdev, struct ib_uverbs_device, dev);
479 struct ib_uverbs_file *file; 619 struct ib_uverbs_file *file;
480 int i = 0;
481 int ret; 620 int ret;
482 621
483 if (!try_module_get(dev->ib_dev->owner)) 622 spin_lock(&map_lock);
484 return -ENODEV; 623 dev = dev_table[iminor(inode) - IB_UVERBS_BASE_MINOR];
624 if (dev)
625 kref_get(&dev->ref);
626 spin_unlock(&map_lock);
627
628 if (!dev)
629 return -ENXIO;
630
631 if (!try_module_get(dev->ib_dev->owner)) {
632 ret = -ENODEV;
633 goto err;
634 }
485 635
486 file = kmalloc(sizeof *file + 636 file = kmalloc(sizeof *file, GFP_KERNEL);
487 (dev->num_comp - 1) * sizeof (struct ib_uverbs_event_file),
488 GFP_KERNEL);
489 if (!file) { 637 if (!file) {
490 ret = -ENOMEM; 638 ret = -ENOMEM;
491 goto err; 639 goto err_module;
492 } 640 }
493 641
494 file->device = dev; 642 file->device = dev;
643 file->ucontext = NULL;
644 file->async_file = NULL;
495 kref_init(&file->ref); 645 kref_init(&file->ref);
496 init_MUTEX(&file->mutex); 646 init_MUTEX(&file->mutex);
497 647
498 file->ucontext = NULL;
499
500 kref_get(&file->ref);
501 ret = ib_uverbs_event_init(&file->async_file, file);
502 if (ret)
503 goto err_kref;
504
505 file->async_file.is_async = 1;
506
507 for (i = 0; i < dev->num_comp; ++i) {
508 kref_get(&file->ref);
509 ret = ib_uverbs_event_init(&file->comp_file[i], file);
510 if (ret)
511 goto err_async;
512 file->comp_file[i].is_async = 0;
513 }
514
515
516 filp->private_data = file; 648 filp->private_data = file;
517 649
518 INIT_IB_EVENT_HANDLER(&file->event_handler, dev->ib_dev,
519 ib_uverbs_event_handler);
520 if (ib_register_event_handler(&file->event_handler))
521 goto err_async;
522
523 return 0; 650 return 0;
524 651
525err_async: 652err_module:
526 while (i--) 653 module_put(dev->ib_dev->owner);
527 ib_uverbs_event_release(&file->comp_file[i]);
528
529 ib_uverbs_event_release(&file->async_file);
530
531err_kref:
532 /*
533 * One extra kref_put() because we took a reference before the
534 * event file creation that failed and got us here.
535 */
536 kref_put(&file->ref, ib_uverbs_release_file);
537 kref_put(&file->ref, ib_uverbs_release_file);
538 654
539err: 655err:
540 module_put(dev->ib_dev->owner); 656 kref_put(&dev->ref, ib_uverbs_release_dev);
657
541 return ret; 658 return ret;
542} 659}
543 660
544static int ib_uverbs_close(struct inode *inode, struct file *filp) 661static int ib_uverbs_close(struct inode *inode, struct file *filp)
545{ 662{
546 struct ib_uverbs_file *file = filp->private_data; 663 struct ib_uverbs_file *file = filp->private_data;
547 int i;
548 664
549 ib_unregister_event_handler(&file->event_handler); 665 ib_uverbs_cleanup_ucontext(file, file->ucontext);
550 ib_uverbs_event_release(&file->async_file);
551 ib_dealloc_ucontext(file->ucontext);
552 666
553 for (i = 0; i < file->device->num_comp; ++i) 667 if (file->async_file)
554 ib_uverbs_event_release(&file->comp_file[i]); 668 kref_put(&file->async_file->ref, ib_uverbs_release_event_file);
555 669
556 kref_put(&file->ref, ib_uverbs_release_file); 670 kref_put(&file->ref, ib_uverbs_release_file);
557 671
@@ -581,27 +695,25 @@ static struct ib_client uverbs_client = {
581 695
582static ssize_t show_ibdev(struct class_device *class_dev, char *buf) 696static ssize_t show_ibdev(struct class_device *class_dev, char *buf)
583{ 697{
584 struct ib_uverbs_device *dev = 698 struct ib_uverbs_device *dev = class_get_devdata(class_dev);
585 container_of(class_dev, struct ib_uverbs_device, class_dev); 699
700 if (!dev)
701 return -ENODEV;
586 702
587 return sprintf(buf, "%s\n", dev->ib_dev->name); 703 return sprintf(buf, "%s\n", dev->ib_dev->name);
588} 704}
589static CLASS_DEVICE_ATTR(ibdev, S_IRUGO, show_ibdev, NULL); 705static CLASS_DEVICE_ATTR(ibdev, S_IRUGO, show_ibdev, NULL);
590 706
591static void ib_uverbs_release_class_dev(struct class_device *class_dev) 707static ssize_t show_dev_abi_version(struct class_device *class_dev, char *buf)
592{ 708{
593 struct ib_uverbs_device *dev = 709 struct ib_uverbs_device *dev = class_get_devdata(class_dev);
594 container_of(class_dev, struct ib_uverbs_device, class_dev);
595 710
596 cdev_del(&dev->dev); 711 if (!dev)
597 clear_bit(dev->devnum, dev_map); 712 return -ENODEV;
598 kfree(dev);
599}
600 713
601static struct class uverbs_class = { 714 return sprintf(buf, "%d\n", dev->ib_dev->uverbs_abi_ver);
602 .name = "infiniband_verbs", 715}
603 .release = ib_uverbs_release_class_dev 716static CLASS_DEVICE_ATTR(abi_version, S_IRUGO, show_dev_abi_version, NULL);
604};
605 717
606static ssize_t show_abi_version(struct class *class, char *buf) 718static ssize_t show_abi_version(struct class *class, char *buf)
607{ 719{
@@ -622,6 +734,8 @@ static void ib_uverbs_add_one(struct ib_device *device)
622 734
623 memset(uverbs_dev, 0, sizeof *uverbs_dev); 735 memset(uverbs_dev, 0, sizeof *uverbs_dev);
624 736
737 kref_init(&uverbs_dev->ref);
738
625 spin_lock(&map_lock); 739 spin_lock(&map_lock);
626 uverbs_dev->devnum = find_first_zero_bit(dev_map, IB_UVERBS_MAX_DEVICES); 740 uverbs_dev->devnum = find_first_zero_bit(dev_map, IB_UVERBS_MAX_DEVICES);
627 if (uverbs_dev->devnum >= IB_UVERBS_MAX_DEVICES) { 741 if (uverbs_dev->devnum >= IB_UVERBS_MAX_DEVICES) {
@@ -631,41 +745,49 @@ static void ib_uverbs_add_one(struct ib_device *device)
631 set_bit(uverbs_dev->devnum, dev_map); 745 set_bit(uverbs_dev->devnum, dev_map);
632 spin_unlock(&map_lock); 746 spin_unlock(&map_lock);
633 747
634 uverbs_dev->ib_dev = device; 748 uverbs_dev->ib_dev = device;
635 uverbs_dev->num_comp = 1; 749 uverbs_dev->num_comp_vectors = 1;
636 750
637 if (device->mmap) 751 uverbs_dev->dev = cdev_alloc();
638 cdev_init(&uverbs_dev->dev, &uverbs_mmap_fops); 752 if (!uverbs_dev->dev)
639 else
640 cdev_init(&uverbs_dev->dev, &uverbs_fops);
641 uverbs_dev->dev.owner = THIS_MODULE;
642 kobject_set_name(&uverbs_dev->dev.kobj, "uverbs%d", uverbs_dev->devnum);
643 if (cdev_add(&uverbs_dev->dev, IB_UVERBS_BASE_DEV + uverbs_dev->devnum, 1))
644 goto err; 753 goto err;
754 uverbs_dev->dev->owner = THIS_MODULE;
755 uverbs_dev->dev->ops = device->mmap ? &uverbs_mmap_fops : &uverbs_fops;
756 kobject_set_name(&uverbs_dev->dev->kobj, "uverbs%d", uverbs_dev->devnum);
757 if (cdev_add(uverbs_dev->dev, IB_UVERBS_BASE_DEV + uverbs_dev->devnum, 1))
758 goto err_cdev;
645 759
646 uverbs_dev->class_dev.class = &uverbs_class; 760 uverbs_dev->class_dev = class_device_create(uverbs_class, NULL,
647 uverbs_dev->class_dev.dev = device->dma_device; 761 uverbs_dev->dev->dev,
648 uverbs_dev->class_dev.devt = uverbs_dev->dev.dev; 762 device->dma_device,
649 snprintf(uverbs_dev->class_dev.class_id, BUS_ID_SIZE, "uverbs%d", uverbs_dev->devnum); 763 "uverbs%d", uverbs_dev->devnum);
650 if (class_device_register(&uverbs_dev->class_dev)) 764 if (IS_ERR(uverbs_dev->class_dev))
651 goto err_cdev; 765 goto err_cdev;
652 766
653 if (class_device_create_file(&uverbs_dev->class_dev, &class_device_attr_ibdev)) 767 class_set_devdata(uverbs_dev->class_dev, uverbs_dev);
768
769 if (class_device_create_file(uverbs_dev->class_dev, &class_device_attr_ibdev))
654 goto err_class; 770 goto err_class;
771 if (class_device_create_file(uverbs_dev->class_dev, &class_device_attr_abi_version))
772 goto err_class;
773
774 spin_lock(&map_lock);
775 dev_table[uverbs_dev->devnum] = uverbs_dev;
776 spin_unlock(&map_lock);
655 777
656 ib_set_client_data(device, &uverbs_client, uverbs_dev); 778 ib_set_client_data(device, &uverbs_client, uverbs_dev);
657 779
658 return; 780 return;
659 781
660err_class: 782err_class:
661 class_device_unregister(&uverbs_dev->class_dev); 783 class_device_destroy(uverbs_class, uverbs_dev->dev->dev);
662 784
663err_cdev: 785err_cdev:
664 cdev_del(&uverbs_dev->dev); 786 cdev_del(uverbs_dev->dev);
665 clear_bit(uverbs_dev->devnum, dev_map); 787 clear_bit(uverbs_dev->devnum, dev_map);
666 788
667err: 789err:
668 kfree(uverbs_dev); 790 kref_put(&uverbs_dev->ref, ib_uverbs_release_dev);
669 return; 791 return;
670} 792}
671 793
@@ -676,7 +798,16 @@ static void ib_uverbs_remove_one(struct ib_device *device)
676 if (!uverbs_dev) 798 if (!uverbs_dev)
677 return; 799 return;
678 800
679 class_device_unregister(&uverbs_dev->class_dev); 801 class_set_devdata(uverbs_dev->class_dev, NULL);
802 class_device_destroy(uverbs_class, uverbs_dev->dev->dev);
803 cdev_del(uverbs_dev->dev);
804
805 spin_lock(&map_lock);
806 dev_table[uverbs_dev->devnum] = NULL;
807 spin_unlock(&map_lock);
808
809 clear_bit(uverbs_dev->devnum, dev_map);
810 kref_put(&uverbs_dev->ref, ib_uverbs_release_dev);
680} 811}
681 812
682static struct super_block *uverbs_event_get_sb(struct file_system_type *fs_type, int flags, 813static struct super_block *uverbs_event_get_sb(struct file_system_type *fs_type, int flags,
@@ -706,13 +837,14 @@ static int __init ib_uverbs_init(void)
706 goto out; 837 goto out;
707 } 838 }
708 839
709 ret = class_register(&uverbs_class); 840 uverbs_class = class_create(THIS_MODULE, "infiniband_verbs");
710 if (ret) { 841 if (IS_ERR(uverbs_class)) {
842 ret = PTR_ERR(uverbs_class);
711 printk(KERN_ERR "user_verbs: couldn't create class infiniband_verbs\n"); 843 printk(KERN_ERR "user_verbs: couldn't create class infiniband_verbs\n");
712 goto out_chrdev; 844 goto out_chrdev;
713 } 845 }
714 846
715 ret = class_create_file(&uverbs_class, &class_attr_abi_version); 847 ret = class_create_file(uverbs_class, &class_attr_abi_version);
716 if (ret) { 848 if (ret) {
717 printk(KERN_ERR "user_verbs: couldn't create abi_version attribute\n"); 849 printk(KERN_ERR "user_verbs: couldn't create abi_version attribute\n");
718 goto out_class; 850 goto out_class;
@@ -746,7 +878,7 @@ out_fs:
746 unregister_filesystem(&uverbs_event_fs); 878 unregister_filesystem(&uverbs_event_fs);
747 879
748out_class: 880out_class:
749 class_unregister(&uverbs_class); 881 class_destroy(uverbs_class);
750 882
751out_chrdev: 883out_chrdev:
752 unregister_chrdev_region(IB_UVERBS_BASE_DEV, IB_UVERBS_MAX_DEVICES); 884 unregister_chrdev_region(IB_UVERBS_BASE_DEV, IB_UVERBS_MAX_DEVICES);
@@ -760,8 +892,15 @@ static void __exit ib_uverbs_cleanup(void)
760 ib_unregister_client(&uverbs_client); 892 ib_unregister_client(&uverbs_client);
761 mntput(uverbs_event_mnt); 893 mntput(uverbs_event_mnt);
762 unregister_filesystem(&uverbs_event_fs); 894 unregister_filesystem(&uverbs_event_fs);
763 class_unregister(&uverbs_class); 895 class_destroy(uverbs_class);
764 unregister_chrdev_region(IB_UVERBS_BASE_DEV, IB_UVERBS_MAX_DEVICES); 896 unregister_chrdev_region(IB_UVERBS_BASE_DEV, IB_UVERBS_MAX_DEVICES);
897 idr_destroy(&ib_uverbs_pd_idr);
898 idr_destroy(&ib_uverbs_mr_idr);
899 idr_destroy(&ib_uverbs_mw_idr);
900 idr_destroy(&ib_uverbs_ah_idr);
901 idr_destroy(&ib_uverbs_cq_idr);
902 idr_destroy(&ib_uverbs_qp_idr);
903 idr_destroy(&ib_uverbs_srq_idr);
765} 904}
766 905
767module_init(ib_uverbs_init); 906module_init(ib_uverbs_init);