Linux kernel & device driver programming

Cross-Referenced Linux and Device Driver Code

[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ]
Version: [ 2.6.11.8 ] [ 2.6.25 ] [ 2.6.25.8 ] [ 2.6.31.13 ] Architecture: [ i386 ]
  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);
199 
  This page was automatically generated by the LXR engine.