Skip to content

Commit b86deba

Browse files
Michal Kalderonjgunthorpe
Michal Kalderon
authored andcommitted
RDMA/core: Move core content from ib_uverbs to ib_core
Move functionality that is called by the driver, which is related to umap, to a new file that will be linked in ib_core. This is a first step in later enabling ib_uverbs to be optional. vm_ops is now initialized in ib_uverbs_mmap instead of priv_init to avoid having to move all the rdma_umap functions as well. Link: https://lore.kernel.org/r/[email protected] Suggested-by: Jason Gunthorpe <[email protected]> Signed-off-by: Ariel Elior <[email protected]> Signed-off-by: Michal Kalderon <[email protected]> Reviewed-by: Jason Gunthorpe <[email protected]> Signed-off-by: Jason Gunthorpe <[email protected]>
1 parent 11f552e commit b86deba

File tree

4 files changed

+86
-72
lines changed

4 files changed

+86
-72
lines changed

drivers/infiniband/core/Makefile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ ib_core-y := packer.o ud_header.o verbs.o cq.o rw.o sysfs.o \
1111
device.o fmr_pool.o cache.o netlink.o \
1212
roce_gid_mgmt.o mr_pool.o addr.o sa_query.o \
1313
multicast.o mad.o smi.o agent.o mad_rmpp.o \
14-
nldev.o restrack.o counters.o
14+
nldev.o restrack.o counters.o ib_core_uverbs.o
1515

1616
ib_core-$(CONFIG_SECURITY_INFINIBAND) += security.o
1717
ib_core-$(CONFIG_CGROUP_RDMA) += cgroup.o

drivers/infiniband/core/core_priv.h

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -387,4 +387,13 @@ int ib_device_set_netns_put(struct sk_buff *skb,
387387

388388
int rdma_nl_net_init(struct rdma_dev_net *rnet);
389389
void rdma_nl_net_exit(struct rdma_dev_net *rnet);
390+
391+
struct rdma_umap_priv {
392+
struct vm_area_struct *vma;
393+
struct list_head list;
394+
};
395+
396+
void rdma_umap_priv_init(struct rdma_umap_priv *priv,
397+
struct vm_area_struct *vma);
398+
390399
#endif /* _CORE_PRIV_H */
Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
1+
// SPDX-License-Identifier: GPL-2.0 OR Linux-OpenIB
2+
/*
3+
* Copyright (c) 2005 Mellanox Technologies. All rights reserved.
4+
* Copyright 2018-2019 Amazon.com, Inc. or its affiliates. All rights reserved.
5+
* Copyright 2019 Marvell. All rights reserved.
6+
*/
7+
#include <linux/xarray.h>
8+
#include "uverbs.h"
9+
#include "core_priv.h"
10+
11+
/*
12+
* Each time we map IO memory into user space this keeps track of the mapping.
13+
* When the device is hot-unplugged we 'zap' the mmaps in user space to point
14+
* to the zero page and allow the hot unplug to proceed.
15+
*
16+
* This is necessary for cases like PCI physical hot unplug as the actual BAR
17+
* memory may vanish after this and access to it from userspace could MCE.
18+
*
19+
* RDMA drivers supporting disassociation must have their user space designed
20+
* to cope in some way with their IO pages going to the zero page.
21+
*/
22+
void rdma_umap_priv_init(struct rdma_umap_priv *priv,
23+
struct vm_area_struct *vma)
24+
{
25+
struct ib_uverbs_file *ufile = vma->vm_file->private_data;
26+
27+
priv->vma = vma;
28+
vma->vm_private_data = priv;
29+
/* vm_ops is setup in ib_uverbs_mmap() to avoid module dependencies */
30+
31+
mutex_lock(&ufile->umap_lock);
32+
list_add(&priv->list, &ufile->umaps);
33+
mutex_unlock(&ufile->umap_lock);
34+
}
35+
EXPORT_SYMBOL(rdma_umap_priv_init);
36+
37+
/*
38+
* Map IO memory into a process. This is to be called by drivers as part of
39+
* their mmap() functions if they wish to send something like PCI-E BAR memory
40+
* to userspace.
41+
*/
42+
int rdma_user_mmap_io(struct ib_ucontext *ucontext, struct vm_area_struct *vma,
43+
unsigned long pfn, unsigned long size, pgprot_t prot)
44+
{
45+
struct ib_uverbs_file *ufile = ucontext->ufile;
46+
struct rdma_umap_priv *priv;
47+
48+
if (!(vma->vm_flags & VM_SHARED))
49+
return -EINVAL;
50+
51+
if (vma->vm_end - vma->vm_start != size)
52+
return -EINVAL;
53+
54+
/* Driver is using this wrong, must be called by ib_uverbs_mmap */
55+
if (WARN_ON(!vma->vm_file ||
56+
vma->vm_file->private_data != ufile))
57+
return -EINVAL;
58+
lockdep_assert_held(&ufile->device->disassociate_srcu);
59+
60+
priv = kzalloc(sizeof(*priv), GFP_KERNEL);
61+
if (!priv)
62+
return -ENOMEM;
63+
64+
vma->vm_page_prot = prot;
65+
if (io_remap_pfn_range(vma, vma->vm_start, pfn, size, prot)) {
66+
kfree(priv);
67+
return -EAGAIN;
68+
}
69+
70+
rdma_umap_priv_init(priv, vma);
71+
return 0;
72+
}
73+
EXPORT_SYMBOL(rdma_user_mmap_io);

drivers/infiniband/core/uverbs_main.c

Lines changed: 3 additions & 71 deletions
Original file line numberDiff line numberDiff line change
@@ -772,6 +772,8 @@ static ssize_t ib_uverbs_write(struct file *filp, const char __user *buf,
772772
return (ret) ? : count;
773773
}
774774

775+
static const struct vm_operations_struct rdma_umap_ops;
776+
775777
static int ib_uverbs_mmap(struct file *filp, struct vm_area_struct *vma)
776778
{
777779
struct ib_uverbs_file *file = filp->private_data;
@@ -785,45 +787,13 @@ static int ib_uverbs_mmap(struct file *filp, struct vm_area_struct *vma)
785787
ret = PTR_ERR(ucontext);
786788
goto out;
787789
}
788-
790+
vma->vm_ops = &rdma_umap_ops;
789791
ret = ucontext->device->ops.mmap(ucontext, vma);
790792
out:
791793
srcu_read_unlock(&file->device->disassociate_srcu, srcu_key);
792794
return ret;
793795
}
794796

795-
/*
796-
* Each time we map IO memory into user space this keeps track of the mapping.
797-
* When the device is hot-unplugged we 'zap' the mmaps in user space to point
798-
* to the zero page and allow the hot unplug to proceed.
799-
*
800-
* This is necessary for cases like PCI physical hot unplug as the actual BAR
801-
* memory may vanish after this and access to it from userspace could MCE.
802-
*
803-
* RDMA drivers supporting disassociation must have their user space designed
804-
* to cope in some way with their IO pages going to the zero page.
805-
*/
806-
struct rdma_umap_priv {
807-
struct vm_area_struct *vma;
808-
struct list_head list;
809-
};
810-
811-
static const struct vm_operations_struct rdma_umap_ops;
812-
813-
static void rdma_umap_priv_init(struct rdma_umap_priv *priv,
814-
struct vm_area_struct *vma)
815-
{
816-
struct ib_uverbs_file *ufile = vma->vm_file->private_data;
817-
818-
priv->vma = vma;
819-
vma->vm_private_data = priv;
820-
vma->vm_ops = &rdma_umap_ops;
821-
822-
mutex_lock(&ufile->umap_lock);
823-
list_add(&priv->list, &ufile->umaps);
824-
mutex_unlock(&ufile->umap_lock);
825-
}
826-
827797
/*
828798
* The VMA has been dup'd, initialize the vm_private_data with a new tracking
829799
* struct
@@ -931,44 +901,6 @@ static const struct vm_operations_struct rdma_umap_ops = {
931901
.fault = rdma_umap_fault,
932902
};
933903

934-
/*
935-
* Map IO memory into a process. This is to be called by drivers as part of
936-
* their mmap() functions if they wish to send something like PCI-E BAR memory
937-
* to userspace.
938-
*/
939-
int rdma_user_mmap_io(struct ib_ucontext *ucontext, struct vm_area_struct *vma,
940-
unsigned long pfn, unsigned long size, pgprot_t prot)
941-
{
942-
struct ib_uverbs_file *ufile = ucontext->ufile;
943-
struct rdma_umap_priv *priv;
944-
945-
if (!(vma->vm_flags & VM_SHARED))
946-
return -EINVAL;
947-
948-
if (vma->vm_end - vma->vm_start != size)
949-
return -EINVAL;
950-
951-
/* Driver is using this wrong, must be called by ib_uverbs_mmap */
952-
if (WARN_ON(!vma->vm_file ||
953-
vma->vm_file->private_data != ufile))
954-
return -EINVAL;
955-
lockdep_assert_held(&ufile->device->disassociate_srcu);
956-
957-
priv = kzalloc(sizeof(*priv), GFP_KERNEL);
958-
if (!priv)
959-
return -ENOMEM;
960-
961-
vma->vm_page_prot = prot;
962-
if (io_remap_pfn_range(vma, vma->vm_start, pfn, size, prot)) {
963-
kfree(priv);
964-
return -EAGAIN;
965-
}
966-
967-
rdma_umap_priv_init(priv, vma);
968-
return 0;
969-
}
970-
EXPORT_SYMBOL(rdma_user_mmap_io);
971-
972904
void uverbs_user_mmap_disassociate(struct ib_uverbs_file *ufile)
973905
{
974906
struct rdma_umap_priv *priv, *next_priv;

0 commit comments

Comments
 (0)