aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/infiniband/core/uverbs_cmd.c
diff options
context:
space:
mode:
authorHaggai Eran <haggaie@mellanox.com>2014-12-11 10:04:18 -0500
committerRoland Dreier <roland@purestorage.com>2014-12-15 21:13:36 -0500
commit882214e2b12860bff1ccff15a3ec2bbb29d58c02 (patch)
treea3609ca71cec22f0c80b4f1b3d5bebf8024051bb /drivers/infiniband/core/uverbs_cmd.c
parent8ada2c1c0c1d75a60723cd2ca7d49c594a146af6 (diff)
IB/core: Implement support for MMU notifiers regarding on demand paging regions
* Add an interval tree implementation for ODP umems. Create an interval tree for each ucontext (including a count of the number of ODP MRs in this context, semaphore, etc.), and register ODP umems in the interval tree. * Add MMU notifiers handling functions, using the interval tree to notify only the relevant umems and underlying MRs. * Register to receive MMU notifier events from the MM subsystem upon ODP MR registration (and unregister accordingly). * Add a completion object to synchronize the destruction of ODP umems. * Add mechanism to abort page faults when there's a concurrent invalidation. The way we synchronize between concurrent invalidations and page faults is by keeping a counter of currently running invalidations, and a sequence number that is incremented whenever an invalidation is caught. The page fault code checks the counter and also verifies that the sequence number hasn't progressed before it updates the umem's page tables. This is similar to what the kvm module does. In order to prevent the case where we register a umem in the middle of an ongoing notifier, we also keep a per ucontext counter of the total number of active mmu notifiers. We only enable new umems when all the running notifiers complete. Signed-off-by: Sagi Grimberg <sagig@mellanox.com> Signed-off-by: Shachar Raindel <raindel@mellanox.com> Signed-off-by: Haggai Eran <haggaie@mellanox.com> Signed-off-by: Yuval Dagan <yuvalda@mellanox.com> Signed-off-by: Roland Dreier <roland@purestorage.com>
Diffstat (limited to 'drivers/infiniband/core/uverbs_cmd.c')
-rw-r--r--drivers/infiniband/core/uverbs_cmd.c17
1 files changed, 17 insertions, 0 deletions
diff --git a/drivers/infiniband/core/uverbs_cmd.c b/drivers/infiniband/core/uverbs_cmd.c
index 70b697d8fbb3..532d8eba8b02 100644
--- a/drivers/infiniband/core/uverbs_cmd.c
+++ b/drivers/infiniband/core/uverbs_cmd.c
@@ -289,6 +289,9 @@ ssize_t ib_uverbs_get_context(struct ib_uverbs_file *file,
289 struct ib_uverbs_get_context_resp resp; 289 struct ib_uverbs_get_context_resp resp;
290 struct ib_udata udata; 290 struct ib_udata udata;
291 struct ib_device *ibdev = file->device->ib_dev; 291 struct ib_device *ibdev = file->device->ib_dev;
292#ifdef CONFIG_INFINIBAND_ON_DEMAND_PAGING
293 struct ib_device_attr dev_attr;
294#endif
292 struct ib_ucontext *ucontext; 295 struct ib_ucontext *ucontext;
293 struct file *filp; 296 struct file *filp;
294 int ret; 297 int ret;
@@ -331,6 +334,20 @@ ssize_t ib_uverbs_get_context(struct ib_uverbs_file *file,
331 rcu_read_unlock(); 334 rcu_read_unlock();
332 ucontext->closing = 0; 335 ucontext->closing = 0;
333 336
337#ifdef CONFIG_INFINIBAND_ON_DEMAND_PAGING
338 ucontext->umem_tree = RB_ROOT;
339 init_rwsem(&ucontext->umem_rwsem);
340 ucontext->odp_mrs_count = 0;
341 INIT_LIST_HEAD(&ucontext->no_private_counters);
342
343 ret = ib_query_device(ibdev, &dev_attr);
344 if (ret)
345 goto err_free;
346 if (!(dev_attr.device_cap_flags & IB_DEVICE_ON_DEMAND_PAGING))
347 ucontext->invalidate_range = NULL;
348
349#endif
350
334 resp.num_comp_vectors = file->device->num_comp_vectors; 351 resp.num_comp_vectors = file->device->num_comp_vectors;
335 352
336 ret = get_unused_fd_flags(O_CLOEXEC); 353 ret = get_unused_fd_flags(O_CLOEXEC);