]> git.karo-electronics.de Git - mv-sheeva.git/blob - drivers/infiniband/hw/ipath/ipath_user_pages.c
[PATCH] IB/ipath: update copyrights and other strings to reflect new company name
[mv-sheeva.git] / drivers / infiniband / hw / ipath / ipath_user_pages.c
1 /*
2  * Copyright (c) 2006 QLogic, Inc. All rights reserved.
3  * Copyright (c) 2003, 2004, 2005, 2006 PathScale, Inc. All rights reserved.
4  *
5  * This software is available to you under a choice of one of two
6  * licenses.  You may choose to be licensed under the terms of the GNU
7  * General Public License (GPL) Version 2, available from the file
8  * COPYING in the main directory of this source tree, or the
9  * OpenIB.org BSD license below:
10  *
11  *     Redistribution and use in source and binary forms, with or
12  *     without modification, are permitted provided that the following
13  *     conditions are met:
14  *
15  *      - Redistributions of source code must retain the above
16  *        copyright notice, this list of conditions and the following
17  *        disclaimer.
18  *
19  *      - Redistributions in binary form must reproduce the above
20  *        copyright notice, this list of conditions and the following
21  *        disclaimer in the documentation and/or other materials
22  *        provided with the distribution.
23  *
24  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
25  * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
26  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
27  * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
28  * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
29  * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
30  * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
31  * SOFTWARE.
32  */
33
34 #include <linux/mm.h>
35 #include <linux/device.h>
36
37 #include "ipath_kernel.h"
38
39 static void __ipath_release_user_pages(struct page **p, size_t num_pages,
40                                    int dirty)
41 {
42         size_t i;
43
44         for (i = 0; i < num_pages; i++) {
45                 ipath_cdbg(MM, "%lu/%lu put_page %p\n", (unsigned long) i,
46                            (unsigned long) num_pages, p[i]);
47                 if (dirty)
48                         set_page_dirty_lock(p[i]);
49                 put_page(p[i]);
50         }
51 }
52
53 /* call with current->mm->mmap_sem held */
54 static int __get_user_pages(unsigned long start_page, size_t num_pages,
55                         struct page **p, struct vm_area_struct **vma)
56 {
57         unsigned long lock_limit;
58         size_t got;
59         int ret;
60
61 #if 0
62         /*
63          * XXX - causes MPI programs to fail, haven't had time to check
64          * yet
65          */
66         if (!capable(CAP_IPC_LOCK)) {
67                 ret = -EPERM;
68                 goto bail;
69         }
70 #endif
71
72         lock_limit = current->signal->rlim[RLIMIT_MEMLOCK].rlim_cur >>
73                 PAGE_SHIFT;
74
75         if (num_pages > lock_limit) {
76                 ret = -ENOMEM;
77                 goto bail;
78         }
79
80         ipath_cdbg(VERBOSE, "pin %lx pages from vaddr %lx\n",
81                    (unsigned long) num_pages, start_page);
82
83         for (got = 0; got < num_pages; got += ret) {
84                 ret = get_user_pages(current, current->mm,
85                                      start_page + got * PAGE_SIZE,
86                                      num_pages - got, 1, 1,
87                                      p + got, vma);
88                 if (ret < 0)
89                         goto bail_release;
90         }
91
92         current->mm->locked_vm += num_pages;
93
94         ret = 0;
95         goto bail;
96
97 bail_release:
98         __ipath_release_user_pages(p, got, 0);
99 bail:
100         return ret;
101 }
102
103 /**
104  * ipath_get_user_pages - lock user pages into memory
105  * @start_page: the start page
106  * @num_pages: the number of pages
107  * @p: the output page structures
108  *
109  * This function takes a given start page (page aligned user virtual
110  * address) and pins it and the following specified number of pages.  For
111  * now, num_pages is always 1, but that will probably change at some point
112  * (because caller is doing expected sends on a single virtually contiguous
113  * buffer, so we can do all pages at once).
114  */
115 int ipath_get_user_pages(unsigned long start_page, size_t num_pages,
116                          struct page **p)
117 {
118         int ret;
119
120         down_write(&current->mm->mmap_sem);
121
122         ret = __get_user_pages(start_page, num_pages, p, NULL);
123
124         up_write(&current->mm->mmap_sem);
125
126         return ret;
127 }
128
129 /**
130  * ipath_get_user_pages_nocopy - lock a single page for I/O and mark shared
131  * @start_page: the page to lock
132  * @p: the output page structure
133  *
134  * This is similar to ipath_get_user_pages, but it's always one page, and we
135  * mark the page as locked for I/O, and shared.  This is used for the user
136  * process page that contains the destination address for the rcvhdrq tail
137  * update, so we need to have the vma. If we don't do this, the page can be
138  * taken away from us on fork, even if the child never touches it, and then
139  * the user process never sees the tail register updates.
140  */
141 int ipath_get_user_pages_nocopy(unsigned long page, struct page **p)
142 {
143         struct vm_area_struct *vma;
144         int ret;
145
146         down_write(&current->mm->mmap_sem);
147
148         ret = __get_user_pages(page, 1, p, &vma);
149
150         up_write(&current->mm->mmap_sem);
151
152         return ret;
153 }
154
155 void ipath_release_user_pages(struct page **p, size_t num_pages)
156 {
157         down_write(&current->mm->mmap_sem);
158
159         __ipath_release_user_pages(p, num_pages, 1);
160
161         current->mm->locked_vm -= num_pages;
162
163         up_write(&current->mm->mmap_sem);
164 }
165
166 struct ipath_user_pages_work {
167         struct work_struct work;
168         struct mm_struct *mm;
169         unsigned long num_pages;
170 };
171
172 static void user_pages_account(void *ptr)
173 {
174         struct ipath_user_pages_work *work = ptr;
175
176         down_write(&work->mm->mmap_sem);
177         work->mm->locked_vm -= work->num_pages;
178         up_write(&work->mm->mmap_sem);
179         mmput(work->mm);
180         kfree(work);
181 }
182
183 void ipath_release_user_pages_on_close(struct page **p, size_t num_pages)
184 {
185         struct ipath_user_pages_work *work;
186         struct mm_struct *mm;
187
188         __ipath_release_user_pages(p, num_pages, 1);
189
190         mm = get_task_mm(current);
191         if (!mm)
192                 goto bail;
193
194         work = kmalloc(sizeof(*work), GFP_KERNEL);
195         if (!work)
196                 goto bail_mm;
197
198         goto bail;
199
200         INIT_WORK(&work->work, user_pages_account, work);
201         work->mm = mm;
202         work->num_pages = num_pages;
203
204 bail_mm:
205         mmput(mm);
206 bail:
207         return;
208 }