aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/infiniband/hw/ipath/ipath_mmap.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/infiniband/hw/ipath/ipath_mmap.c')
-rw-r--r--drivers/infiniband/hw/ipath/ipath_mmap.c64
1 files changed, 58 insertions, 6 deletions
diff --git a/drivers/infiniband/hw/ipath/ipath_mmap.c b/drivers/infiniband/hw/ipath/ipath_mmap.c
index a82157db4689..937bc3396b53 100644
--- a/drivers/infiniband/hw/ipath/ipath_mmap.c
+++ b/drivers/infiniband/hw/ipath/ipath_mmap.c
@@ -46,6 +46,11 @@ void ipath_release_mmap_info(struct kref *ref)
46{ 46{
47 struct ipath_mmap_info *ip = 47 struct ipath_mmap_info *ip =
48 container_of(ref, struct ipath_mmap_info, ref); 48 container_of(ref, struct ipath_mmap_info, ref);
49 struct ipath_ibdev *dev = to_idev(ip->context->device);
50
51 spin_lock_irq(&dev->pending_lock);
52 list_del(&ip->pending_mmaps);
53 spin_unlock_irq(&dev->pending_lock);
49 54
50 vfree(ip->obj); 55 vfree(ip->obj);
51 kfree(ip); 56 kfree(ip);
@@ -60,14 +65,12 @@ static void ipath_vma_open(struct vm_area_struct *vma)
60 struct ipath_mmap_info *ip = vma->vm_private_data; 65 struct ipath_mmap_info *ip = vma->vm_private_data;
61 66
62 kref_get(&ip->ref); 67 kref_get(&ip->ref);
63 ip->mmap_cnt++;
64} 68}
65 69
66static void ipath_vma_close(struct vm_area_struct *vma) 70static void ipath_vma_close(struct vm_area_struct *vma)
67{ 71{
68 struct ipath_mmap_info *ip = vma->vm_private_data; 72 struct ipath_mmap_info *ip = vma->vm_private_data;
69 73
70 ip->mmap_cnt--;
71 kref_put(&ip->ref, ipath_release_mmap_info); 74 kref_put(&ip->ref, ipath_release_mmap_info);
72} 75}
73 76
@@ -87,7 +90,7 @@ int ipath_mmap(struct ib_ucontext *context, struct vm_area_struct *vma)
87 struct ipath_ibdev *dev = to_idev(context->device); 90 struct ipath_ibdev *dev = to_idev(context->device);
88 unsigned long offset = vma->vm_pgoff << PAGE_SHIFT; 91 unsigned long offset = vma->vm_pgoff << PAGE_SHIFT;
89 unsigned long size = vma->vm_end - vma->vm_start; 92 unsigned long size = vma->vm_end - vma->vm_start;
90 struct ipath_mmap_info *ip, **pp; 93 struct ipath_mmap_info *ip, *pp;
91 int ret = -EINVAL; 94 int ret = -EINVAL;
92 95
93 /* 96 /*
@@ -96,15 +99,16 @@ int ipath_mmap(struct ib_ucontext *context, struct vm_area_struct *vma)
96 * CQ, QP, or SRQ is soon followed by a call to mmap(). 99 * CQ, QP, or SRQ is soon followed by a call to mmap().
97 */ 100 */
98 spin_lock_irq(&dev->pending_lock); 101 spin_lock_irq(&dev->pending_lock);
99 for (pp = &dev->pending_mmaps; (ip = *pp); pp = &ip->next) { 102 list_for_each_entry_safe(ip, pp, &dev->pending_mmaps,
103 pending_mmaps) {
100 /* Only the creator is allowed to mmap the object */ 104 /* Only the creator is allowed to mmap the object */
101 if (context != ip->context || (void *) offset != ip->obj) 105 if (context != ip->context || (__u64) offset != ip->offset)
102 continue; 106 continue;
103 /* Don't allow a mmap larger than the object. */ 107 /* Don't allow a mmap larger than the object. */
104 if (size > ip->size) 108 if (size > ip->size)
105 break; 109 break;
106 110
107 *pp = ip->next; 111 list_del_init(&ip->pending_mmaps);
108 spin_unlock_irq(&dev->pending_lock); 112 spin_unlock_irq(&dev->pending_lock);
109 113
110 ret = remap_vmalloc_range(vma, ip->obj, 0); 114 ret = remap_vmalloc_range(vma, ip->obj, 0);
@@ -119,3 +123,51 @@ int ipath_mmap(struct ib_ucontext *context, struct vm_area_struct *vma)
119done: 123done:
120 return ret; 124 return ret;
121} 125}
126
127/*
128 * Allocate information for ipath_mmap
129 */
130struct ipath_mmap_info *ipath_create_mmap_info(struct ipath_ibdev *dev,
131 u32 size,
132 struct ib_ucontext *context,
133 void *obj) {
134 struct ipath_mmap_info *ip;
135
136 ip = kmalloc(sizeof *ip, GFP_KERNEL);
137 if (!ip)
138 goto bail;
139
140 size = PAGE_ALIGN(size);
141
142 spin_lock_irq(&dev->mmap_offset_lock);
143 if (dev->mmap_offset == 0)
144 dev->mmap_offset = PAGE_SIZE;
145 ip->offset = dev->mmap_offset;
146 dev->mmap_offset += size;
147 spin_unlock_irq(&dev->mmap_offset_lock);
148
149 INIT_LIST_HEAD(&ip->pending_mmaps);
150 ip->size = size;
151 ip->context = context;
152 ip->obj = obj;
153 kref_init(&ip->ref);
154
155bail:
156 return ip;
157}
158
159void ipath_update_mmap_info(struct ipath_ibdev *dev,
160 struct ipath_mmap_info *ip,
161 u32 size, void *obj) {
162 size = PAGE_ALIGN(size);
163
164 spin_lock_irq(&dev->mmap_offset_lock);
165 if (dev->mmap_offset == 0)
166 dev->mmap_offset = PAGE_SIZE;
167 ip->offset = dev->mmap_offset;
168 dev->mmap_offset += size;
169 spin_unlock_irq(&dev->mmap_offset_lock);
170
171 ip->size = size;
172 ip->obj = obj;
173}