]> pilppa.org Git - linux-2.6-omap-h63xx.git/blob - drivers/net/mlx4/alloc.c
Merge branch 'release' of git://git.kernel.org/pub/scm/linux/kernel/git/aegl/linux-2.6
[linux-2.6-omap-h63xx.git] / drivers / net / mlx4 / alloc.c
1 /*
2  * Copyright (c) 2006, 2007 Cisco Systems, Inc.  All rights reserved.
3  *
4  * This software is available to you under a choice of one of two
5  * licenses.  You may choose to be licensed under the terms of the GNU
6  * General Public License (GPL) Version 2, available from the file
7  * COPYING in the main directory of this source tree, or the
8  * OpenIB.org BSD license below:
9  *
10  *     Redistribution and use in source and binary forms, with or
11  *     without modification, are permitted provided that the following
12  *     conditions are met:
13  *
14  *      - Redistributions of source code must retain the above
15  *        copyright notice, this list of conditions and the following
16  *        disclaimer.
17  *
18  *      - Redistributions in binary form must reproduce the above
19  *        copyright notice, this list of conditions and the following
20  *        disclaimer in the documentation and/or other materials
21  *        provided with the distribution.
22  *
23  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
24  * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
25  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
26  * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
27  * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
28  * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
29  * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
30  * SOFTWARE.
31  */
32
33 #include <linux/errno.h>
34 #include <linux/slab.h>
35 #include <linux/bitmap.h>
36 #include <linux/dma-mapping.h>
37 #include <linux/vmalloc.h>
38
39 #include "mlx4.h"
40
41 u32 mlx4_bitmap_alloc(struct mlx4_bitmap *bitmap)
42 {
43         u32 obj;
44
45         spin_lock(&bitmap->lock);
46
47         obj = find_next_zero_bit(bitmap->table, bitmap->max, bitmap->last);
48         if (obj >= bitmap->max) {
49                 bitmap->top = (bitmap->top + bitmap->max) & bitmap->mask;
50                 obj = find_first_zero_bit(bitmap->table, bitmap->max);
51         }
52
53         if (obj < bitmap->max) {
54                 set_bit(obj, bitmap->table);
55                 bitmap->last = (obj + 1) & (bitmap->max - 1);
56                 obj |= bitmap->top;
57         } else
58                 obj = -1;
59
60         spin_unlock(&bitmap->lock);
61
62         return obj;
63 }
64
65 void mlx4_bitmap_free(struct mlx4_bitmap *bitmap, u32 obj)
66 {
67         obj &= bitmap->max - 1;
68
69         spin_lock(&bitmap->lock);
70         clear_bit(obj, bitmap->table);
71         bitmap->last = min(bitmap->last, obj);
72         bitmap->top = (bitmap->top + bitmap->max) & bitmap->mask;
73         spin_unlock(&bitmap->lock);
74 }
75
76 int mlx4_bitmap_init(struct mlx4_bitmap *bitmap, u32 num, u32 mask, u32 reserved)
77 {
78         int i;
79
80         /* num must be a power of 2 */
81         if (num != roundup_pow_of_two(num))
82                 return -EINVAL;
83
84         bitmap->last = 0;
85         bitmap->top  = 0;
86         bitmap->max  = num;
87         bitmap->mask = mask;
88         spin_lock_init(&bitmap->lock);
89         bitmap->table = kzalloc(BITS_TO_LONGS(num) * sizeof (long), GFP_KERNEL);
90         if (!bitmap->table)
91                 return -ENOMEM;
92
93         for (i = 0; i < reserved; ++i)
94                 set_bit(i, bitmap->table);
95
96         return 0;
97 }
98
99 void mlx4_bitmap_cleanup(struct mlx4_bitmap *bitmap)
100 {
101         kfree(bitmap->table);
102 }
103
104 /*
105  * Handling for queue buffers -- we allocate a bunch of memory and
106  * register it in a memory region at HCA virtual address 0.  If the
107  * requested size is > max_direct, we split the allocation into
108  * multiple pages, so we don't require too much contiguous memory.
109  */
110
111 int mlx4_buf_alloc(struct mlx4_dev *dev, int size, int max_direct,
112                    struct mlx4_buf *buf)
113 {
114         dma_addr_t t;
115
116         if (size <= max_direct) {
117                 buf->nbufs        = 1;
118                 buf->npages       = 1;
119                 buf->page_shift   = get_order(size) + PAGE_SHIFT;
120                 buf->direct.buf   = dma_alloc_coherent(&dev->pdev->dev,
121                                                        size, &t, GFP_KERNEL);
122                 if (!buf->direct.buf)
123                         return -ENOMEM;
124
125                 buf->direct.map = t;
126
127                 while (t & ((1 << buf->page_shift) - 1)) {
128                         --buf->page_shift;
129                         buf->npages *= 2;
130                 }
131
132                 memset(buf->direct.buf, 0, size);
133         } else {
134                 int i;
135
136                 buf->nbufs       = (size + PAGE_SIZE - 1) / PAGE_SIZE;
137                 buf->npages      = buf->nbufs;
138                 buf->page_shift  = PAGE_SHIFT;
139                 buf->page_list   = kzalloc(buf->nbufs * sizeof *buf->page_list,
140                                            GFP_KERNEL);
141                 if (!buf->page_list)
142                         return -ENOMEM;
143
144                 for (i = 0; i < buf->nbufs; ++i) {
145                         buf->page_list[i].buf =
146                                 dma_alloc_coherent(&dev->pdev->dev, PAGE_SIZE,
147                                                    &t, GFP_KERNEL);
148                         if (!buf->page_list[i].buf)
149                                 goto err_free;
150
151                         buf->page_list[i].map = t;
152
153                         memset(buf->page_list[i].buf, 0, PAGE_SIZE);
154                 }
155
156                 if (BITS_PER_LONG == 64) {
157                         struct page **pages;
158                         pages = kmalloc(sizeof *pages * buf->nbufs, GFP_KERNEL);
159                         if (!pages)
160                                 goto err_free;
161                         for (i = 0; i < buf->nbufs; ++i)
162                                 pages[i] = virt_to_page(buf->page_list[i].buf);
163                         buf->direct.buf = vmap(pages, buf->nbufs, VM_MAP, PAGE_KERNEL);
164                         kfree(pages);
165                         if (!buf->direct.buf)
166                                 goto err_free;
167                 }
168         }
169
170         return 0;
171
172 err_free:
173         mlx4_buf_free(dev, size, buf);
174
175         return -ENOMEM;
176 }
177 EXPORT_SYMBOL_GPL(mlx4_buf_alloc);
178
179 void mlx4_buf_free(struct mlx4_dev *dev, int size, struct mlx4_buf *buf)
180 {
181         int i;
182
183         if (buf->nbufs == 1)
184                 dma_free_coherent(&dev->pdev->dev, size, buf->direct.buf,
185                                   buf->direct.map);
186         else {
187                 if (BITS_PER_LONG == 64)
188                         vunmap(buf->direct.buf);
189
190                 for (i = 0; i < buf->nbufs; ++i)
191                         if (buf->page_list[i].buf)
192                                 dma_free_coherent(&dev->pdev->dev, PAGE_SIZE,
193                                                   buf->page_list[i].buf,
194                                                   buf->page_list[i].map);
195                 kfree(buf->page_list);
196         }
197 }
198 EXPORT_SYMBOL_GPL(mlx4_buf_free);