diff options
author | Jeff Kirsher <jeffrey.t.kirsher@intel.com> | 2011-05-13 04:32:22 -0400 |
---|---|---|
committer | Jeff Kirsher <jeffrey.t.kirsher@intel.com> | 2011-08-11 05:41:35 -0400 |
commit | 5a2cc190eb3fe58fe519795c509b01b25795992e (patch) | |
tree | 9a319736bd77979ab5dbdc26d29424d84eb235b0 /drivers/net/mlx4/alloc.c | |
parent | f844a0ead401c3ce0f01a8bb4d6cea2f0f6ad863 (diff) |
mlx4: Move the Mellanox driver
Moves the Mellanox driver into drivers/net/ethernet/mellanox/ and
make the necessary Kconfig and Makefile changes.
CC: Roland Dreier <roland@kernel.org>
Signed-off-by: Jeff Kirsher <jeffrey.t.kirsher@intel.com>
Diffstat (limited to 'drivers/net/mlx4/alloc.c')
-rw-r--r-- | drivers/net/mlx4/alloc.c | 414 |
1 files changed, 0 insertions, 414 deletions
diff --git a/drivers/net/mlx4/alloc.c b/drivers/net/mlx4/alloc.c deleted file mode 100644 index 116cae334dad..000000000000 --- a/drivers/net/mlx4/alloc.c +++ /dev/null | |||
@@ -1,414 +0,0 @@ | |||
1 | /* | ||
2 | * Copyright (c) 2006, 2007 Cisco Systems, Inc. All rights reserved. | ||
3 | * Copyright (c) 2007, 2008 Mellanox Technologies. 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/errno.h> | ||
35 | #include <linux/slab.h> | ||
36 | #include <linux/mm.h> | ||
37 | #include <linux/bitmap.h> | ||
38 | #include <linux/dma-mapping.h> | ||
39 | #include <linux/vmalloc.h> | ||
40 | |||
41 | #include "mlx4.h" | ||
42 | |||
43 | u32 mlx4_bitmap_alloc(struct mlx4_bitmap *bitmap) | ||
44 | { | ||
45 | u32 obj; | ||
46 | |||
47 | spin_lock(&bitmap->lock); | ||
48 | |||
49 | obj = find_next_zero_bit(bitmap->table, bitmap->max, bitmap->last); | ||
50 | if (obj >= bitmap->max) { | ||
51 | bitmap->top = (bitmap->top + bitmap->max + bitmap->reserved_top) | ||
52 | & bitmap->mask; | ||
53 | obj = find_first_zero_bit(bitmap->table, bitmap->max); | ||
54 | } | ||
55 | |||
56 | if (obj < bitmap->max) { | ||
57 | set_bit(obj, bitmap->table); | ||
58 | bitmap->last = (obj + 1); | ||
59 | if (bitmap->last == bitmap->max) | ||
60 | bitmap->last = 0; | ||
61 | obj |= bitmap->top; | ||
62 | } else | ||
63 | obj = -1; | ||
64 | |||
65 | if (obj != -1) | ||
66 | --bitmap->avail; | ||
67 | |||
68 | spin_unlock(&bitmap->lock); | ||
69 | |||
70 | return obj; | ||
71 | } | ||
72 | |||
73 | void mlx4_bitmap_free(struct mlx4_bitmap *bitmap, u32 obj) | ||
74 | { | ||
75 | mlx4_bitmap_free_range(bitmap, obj, 1); | ||
76 | } | ||
77 | |||
78 | u32 mlx4_bitmap_alloc_range(struct mlx4_bitmap *bitmap, int cnt, int align) | ||
79 | { | ||
80 | u32 obj; | ||
81 | |||
82 | if (likely(cnt == 1 && align == 1)) | ||
83 | return mlx4_bitmap_alloc(bitmap); | ||
84 | |||
85 | spin_lock(&bitmap->lock); | ||
86 | |||
87 | obj = bitmap_find_next_zero_area(bitmap->table, bitmap->max, | ||
88 | bitmap->last, cnt, align - 1); | ||
89 | if (obj >= bitmap->max) { | ||
90 | bitmap->top = (bitmap->top + bitmap->max + bitmap->reserved_top) | ||
91 | & bitmap->mask; | ||
92 | obj = bitmap_find_next_zero_area(bitmap->table, bitmap->max, | ||
93 | 0, cnt, align - 1); | ||
94 | } | ||
95 | |||
96 | if (obj < bitmap->max) { | ||
97 | bitmap_set(bitmap->table, obj, cnt); | ||
98 | if (obj == bitmap->last) { | ||
99 | bitmap->last = (obj + cnt); | ||
100 | if (bitmap->last >= bitmap->max) | ||
101 | bitmap->last = 0; | ||
102 | } | ||
103 | obj |= bitmap->top; | ||
104 | } else | ||
105 | obj = -1; | ||
106 | |||
107 | if (obj != -1) | ||
108 | bitmap->avail -= cnt; | ||
109 | |||
110 | spin_unlock(&bitmap->lock); | ||
111 | |||
112 | return obj; | ||
113 | } | ||
114 | |||
115 | u32 mlx4_bitmap_avail(struct mlx4_bitmap *bitmap) | ||
116 | { | ||
117 | return bitmap->avail; | ||
118 | } | ||
119 | |||
120 | void mlx4_bitmap_free_range(struct mlx4_bitmap *bitmap, u32 obj, int cnt) | ||
121 | { | ||
122 | obj &= bitmap->max + bitmap->reserved_top - 1; | ||
123 | |||
124 | spin_lock(&bitmap->lock); | ||
125 | bitmap_clear(bitmap->table, obj, cnt); | ||
126 | bitmap->last = min(bitmap->last, obj); | ||
127 | bitmap->top = (bitmap->top + bitmap->max + bitmap->reserved_top) | ||
128 | & bitmap->mask; | ||
129 | bitmap->avail += cnt; | ||
130 | spin_unlock(&bitmap->lock); | ||
131 | } | ||
132 | |||
133 | int mlx4_bitmap_init(struct mlx4_bitmap *bitmap, u32 num, u32 mask, | ||
134 | u32 reserved_bot, u32 reserved_top) | ||
135 | { | ||
136 | /* num must be a power of 2 */ | ||
137 | if (num != roundup_pow_of_two(num)) | ||
138 | return -EINVAL; | ||
139 | |||
140 | bitmap->last = 0; | ||
141 | bitmap->top = 0; | ||
142 | bitmap->max = num - reserved_top; | ||
143 | bitmap->mask = mask; | ||
144 | bitmap->reserved_top = reserved_top; | ||
145 | bitmap->avail = num - reserved_top - reserved_bot; | ||
146 | spin_lock_init(&bitmap->lock); | ||
147 | bitmap->table = kzalloc(BITS_TO_LONGS(bitmap->max) * | ||
148 | sizeof (long), GFP_KERNEL); | ||
149 | if (!bitmap->table) | ||
150 | return -ENOMEM; | ||
151 | |||
152 | bitmap_set(bitmap->table, 0, reserved_bot); | ||
153 | |||
154 | return 0; | ||
155 | } | ||
156 | |||
157 | void mlx4_bitmap_cleanup(struct mlx4_bitmap *bitmap) | ||
158 | { | ||
159 | kfree(bitmap->table); | ||
160 | } | ||
161 | |||
162 | /* | ||
163 | * Handling for queue buffers -- we allocate a bunch of memory and | ||
164 | * register it in a memory region at HCA virtual address 0. If the | ||
165 | * requested size is > max_direct, we split the allocation into | ||
166 | * multiple pages, so we don't require too much contiguous memory. | ||
167 | */ | ||
168 | |||
169 | int mlx4_buf_alloc(struct mlx4_dev *dev, int size, int max_direct, | ||
170 | struct mlx4_buf *buf) | ||
171 | { | ||
172 | dma_addr_t t; | ||
173 | |||
174 | if (size <= max_direct) { | ||
175 | buf->nbufs = 1; | ||
176 | buf->npages = 1; | ||
177 | buf->page_shift = get_order(size) + PAGE_SHIFT; | ||
178 | buf->direct.buf = dma_alloc_coherent(&dev->pdev->dev, | ||
179 | size, &t, GFP_KERNEL); | ||
180 | if (!buf->direct.buf) | ||
181 | return -ENOMEM; | ||
182 | |||
183 | buf->direct.map = t; | ||
184 | |||
185 | while (t & ((1 << buf->page_shift) - 1)) { | ||
186 | --buf->page_shift; | ||
187 | buf->npages *= 2; | ||
188 | } | ||
189 | |||
190 | memset(buf->direct.buf, 0, size); | ||
191 | } else { | ||
192 | int i; | ||
193 | |||
194 | buf->direct.buf = NULL; | ||
195 | buf->nbufs = (size + PAGE_SIZE - 1) / PAGE_SIZE; | ||
196 | buf->npages = buf->nbufs; | ||
197 | buf->page_shift = PAGE_SHIFT; | ||
198 | buf->page_list = kcalloc(buf->nbufs, sizeof(*buf->page_list), | ||
199 | GFP_KERNEL); | ||
200 | if (!buf->page_list) | ||
201 | return -ENOMEM; | ||
202 | |||
203 | for (i = 0; i < buf->nbufs; ++i) { | ||
204 | buf->page_list[i].buf = | ||
205 | dma_alloc_coherent(&dev->pdev->dev, PAGE_SIZE, | ||
206 | &t, GFP_KERNEL); | ||
207 | if (!buf->page_list[i].buf) | ||
208 | goto err_free; | ||
209 | |||
210 | buf->page_list[i].map = t; | ||
211 | |||
212 | memset(buf->page_list[i].buf, 0, PAGE_SIZE); | ||
213 | } | ||
214 | |||
215 | if (BITS_PER_LONG == 64) { | ||
216 | struct page **pages; | ||
217 | pages = kmalloc(sizeof *pages * buf->nbufs, GFP_KERNEL); | ||
218 | if (!pages) | ||
219 | goto err_free; | ||
220 | for (i = 0; i < buf->nbufs; ++i) | ||
221 | pages[i] = virt_to_page(buf->page_list[i].buf); | ||
222 | buf->direct.buf = vmap(pages, buf->nbufs, VM_MAP, PAGE_KERNEL); | ||
223 | kfree(pages); | ||
224 | if (!buf->direct.buf) | ||
225 | goto err_free; | ||
226 | } | ||
227 | } | ||
228 | |||
229 | return 0; | ||
230 | |||
231 | err_free: | ||
232 | mlx4_buf_free(dev, size, buf); | ||
233 | |||
234 | return -ENOMEM; | ||
235 | } | ||
236 | EXPORT_SYMBOL_GPL(mlx4_buf_alloc); | ||
237 | |||
238 | void mlx4_buf_free(struct mlx4_dev *dev, int size, struct mlx4_buf *buf) | ||
239 | { | ||
240 | int i; | ||
241 | |||
242 | if (buf->nbufs == 1) | ||
243 | dma_free_coherent(&dev->pdev->dev, size, buf->direct.buf, | ||
244 | buf->direct.map); | ||
245 | else { | ||
246 | if (BITS_PER_LONG == 64 && buf->direct.buf) | ||
247 | vunmap(buf->direct.buf); | ||
248 | |||
249 | for (i = 0; i < buf->nbufs; ++i) | ||
250 | if (buf->page_list[i].buf) | ||
251 | dma_free_coherent(&dev->pdev->dev, PAGE_SIZE, | ||
252 | buf->page_list[i].buf, | ||
253 | buf->page_list[i].map); | ||
254 | kfree(buf->page_list); | ||
255 | } | ||
256 | } | ||
257 | EXPORT_SYMBOL_GPL(mlx4_buf_free); | ||
258 | |||
259 | static struct mlx4_db_pgdir *mlx4_alloc_db_pgdir(struct device *dma_device) | ||
260 | { | ||
261 | struct mlx4_db_pgdir *pgdir; | ||
262 | |||
263 | pgdir = kzalloc(sizeof *pgdir, GFP_KERNEL); | ||
264 | if (!pgdir) | ||
265 | return NULL; | ||
266 | |||
267 | bitmap_fill(pgdir->order1, MLX4_DB_PER_PAGE / 2); | ||
268 | pgdir->bits[0] = pgdir->order0; | ||
269 | pgdir->bits[1] = pgdir->order1; | ||
270 | pgdir->db_page = dma_alloc_coherent(dma_device, PAGE_SIZE, | ||
271 | &pgdir->db_dma, GFP_KERNEL); | ||
272 | if (!pgdir->db_page) { | ||
273 | kfree(pgdir); | ||
274 | return NULL; | ||
275 | } | ||
276 | |||
277 | return pgdir; | ||
278 | } | ||
279 | |||
280 | static int mlx4_alloc_db_from_pgdir(struct mlx4_db_pgdir *pgdir, | ||
281 | struct mlx4_db *db, int order) | ||
282 | { | ||
283 | int o; | ||
284 | int i; | ||
285 | |||
286 | for (o = order; o <= 1; ++o) { | ||
287 | i = find_first_bit(pgdir->bits[o], MLX4_DB_PER_PAGE >> o); | ||
288 | if (i < MLX4_DB_PER_PAGE >> o) | ||
289 | goto found; | ||
290 | } | ||
291 | |||
292 | return -ENOMEM; | ||
293 | |||
294 | found: | ||
295 | clear_bit(i, pgdir->bits[o]); | ||
296 | |||
297 | i <<= o; | ||
298 | |||
299 | if (o > order) | ||
300 | set_bit(i ^ 1, pgdir->bits[order]); | ||
301 | |||
302 | db->u.pgdir = pgdir; | ||
303 | db->index = i; | ||
304 | db->db = pgdir->db_page + db->index; | ||
305 | db->dma = pgdir->db_dma + db->index * 4; | ||
306 | db->order = order; | ||
307 | |||
308 | return 0; | ||
309 | } | ||
310 | |||
311 | int mlx4_db_alloc(struct mlx4_dev *dev, struct mlx4_db *db, int order) | ||
312 | { | ||
313 | struct mlx4_priv *priv = mlx4_priv(dev); | ||
314 | struct mlx4_db_pgdir *pgdir; | ||
315 | int ret = 0; | ||
316 | |||
317 | mutex_lock(&priv->pgdir_mutex); | ||
318 | |||
319 | list_for_each_entry(pgdir, &priv->pgdir_list, list) | ||
320 | if (!mlx4_alloc_db_from_pgdir(pgdir, db, order)) | ||
321 | goto out; | ||
322 | |||
323 | pgdir = mlx4_alloc_db_pgdir(&(dev->pdev->dev)); | ||
324 | if (!pgdir) { | ||
325 | ret = -ENOMEM; | ||
326 | goto out; | ||
327 | } | ||
328 | |||
329 | list_add(&pgdir->list, &priv->pgdir_list); | ||
330 | |||
331 | /* This should never fail -- we just allocated an empty page: */ | ||
332 | WARN_ON(mlx4_alloc_db_from_pgdir(pgdir, db, order)); | ||
333 | |||
334 | out: | ||
335 | mutex_unlock(&priv->pgdir_mutex); | ||
336 | |||
337 | return ret; | ||
338 | } | ||
339 | EXPORT_SYMBOL_GPL(mlx4_db_alloc); | ||
340 | |||
341 | void mlx4_db_free(struct mlx4_dev *dev, struct mlx4_db *db) | ||
342 | { | ||
343 | struct mlx4_priv *priv = mlx4_priv(dev); | ||
344 | int o; | ||
345 | int i; | ||
346 | |||
347 | mutex_lock(&priv->pgdir_mutex); | ||
348 | |||
349 | o = db->order; | ||
350 | i = db->index; | ||
351 | |||
352 | if (db->order == 0 && test_bit(i ^ 1, db->u.pgdir->order0)) { | ||
353 | clear_bit(i ^ 1, db->u.pgdir->order0); | ||
354 | ++o; | ||
355 | } | ||
356 | i >>= o; | ||
357 | set_bit(i, db->u.pgdir->bits[o]); | ||
358 | |||
359 | if (bitmap_full(db->u.pgdir->order1, MLX4_DB_PER_PAGE / 2)) { | ||
360 | dma_free_coherent(&(dev->pdev->dev), PAGE_SIZE, | ||
361 | db->u.pgdir->db_page, db->u.pgdir->db_dma); | ||
362 | list_del(&db->u.pgdir->list); | ||
363 | kfree(db->u.pgdir); | ||
364 | } | ||
365 | |||
366 | mutex_unlock(&priv->pgdir_mutex); | ||
367 | } | ||
368 | EXPORT_SYMBOL_GPL(mlx4_db_free); | ||
369 | |||
370 | int mlx4_alloc_hwq_res(struct mlx4_dev *dev, struct mlx4_hwq_resources *wqres, | ||
371 | int size, int max_direct) | ||
372 | { | ||
373 | int err; | ||
374 | |||
375 | err = mlx4_db_alloc(dev, &wqres->db, 1); | ||
376 | if (err) | ||
377 | return err; | ||
378 | |||
379 | *wqres->db.db = 0; | ||
380 | |||
381 | err = mlx4_buf_alloc(dev, size, max_direct, &wqres->buf); | ||
382 | if (err) | ||
383 | goto err_db; | ||
384 | |||
385 | err = mlx4_mtt_init(dev, wqres->buf.npages, wqres->buf.page_shift, | ||
386 | &wqres->mtt); | ||
387 | if (err) | ||
388 | goto err_buf; | ||
389 | |||
390 | err = mlx4_buf_write_mtt(dev, &wqres->mtt, &wqres->buf); | ||
391 | if (err) | ||
392 | goto err_mtt; | ||
393 | |||
394 | return 0; | ||
395 | |||
396 | err_mtt: | ||
397 | mlx4_mtt_cleanup(dev, &wqres->mtt); | ||
398 | err_buf: | ||
399 | mlx4_buf_free(dev, size, &wqres->buf); | ||
400 | err_db: | ||
401 | mlx4_db_free(dev, &wqres->db); | ||
402 | |||
403 | return err; | ||
404 | } | ||
405 | EXPORT_SYMBOL_GPL(mlx4_alloc_hwq_res); | ||
406 | |||
407 | void mlx4_free_hwq_res(struct mlx4_dev *dev, struct mlx4_hwq_resources *wqres, | ||
408 | int size) | ||
409 | { | ||
410 | mlx4_mtt_cleanup(dev, &wqres->mtt); | ||
411 | mlx4_buf_free(dev, size, &wqres->buf); | ||
412 | mlx4_db_free(dev, &wqres->db); | ||
413 | } | ||
414 | EXPORT_SYMBOL_GPL(mlx4_free_hwq_res); | ||