v2.4.8 -> v2.4.8.1
[opensuse:kernel.git] / arch / arm / mach-sa1100 / pcipool.c
1 /*
2   NOTE:
3
4   this code was lifted straight out of drivers/pci/pci.c;
5   when compiling for the Intel StrongARM SA-1110/SA-1111 the
6   usb-ohci.c driver needs these routines even when the architecture
7   has no pci bus...
8 */
9
10 #include <linux/config.h>
11 #include <linux/module.h>
12 #include <linux/types.h>
13 #include <linux/kernel.h>
14 #include <linux/pci.h>
15 #include <linux/string.h>
16 #include <linux/init.h>
17 #include <linux/slab.h>
18 #include <linux/spinlock.h>
19 #include <linux/bitops.h>
20
21 #include <asm/page.h>
22
23 #include "pcipool.h"
24
25 /*
26  * Pool allocator ... wraps the pci_alloc_consistent page allocator, so
27  * small blocks are easily used by drivers for bus mastering controllers.
28  * This should probably be sharing the guts of the slab allocator.
29  */
30
31 struct pci_pool {       /* the pool */
32         struct list_head        page_list;
33         spinlock_t              lock;
34         size_t                  blocks_per_page;
35         size_t                  size;
36         int                     flags;
37         struct pci_dev          *dev;
38         size_t                  allocation;
39         char                    name [32];
40         wait_queue_head_t       waitq;
41 };
42
43 struct pci_page {       /* cacheable header for 'allocation' bytes */
44         struct list_head        page_list;
45         void                    *vaddr;
46         dma_addr_t              dma;
47         unsigned long           bitmap [0];
48 };
49
50 #define POOL_TIMEOUT_JIFFIES    ((100 /* msec */ * HZ) / 1000)
51 #define POOL_POISON_BYTE        0xa7
52
53 // #define CONFIG_PCIPOOL_DEBUG
54
55
56 /**
57  * pci_pool_create - Creates a pool of pci consistent memory blocks, for dma.
58  * @name: name of pool, for diagnostics
59  * @pdev: pci device that will be doing the DMA
60  * @size: size of the blocks in this pool.
61  * @align: alignment requirement for blocks; must be a power of two
62  * @allocation: returned blocks won't cross this boundary (or zero)
63  * @flags: SLAB_* flags (not all are supported).
64  *
65  * Returns a pci allocation pool with the requested characteristics, or
66  * null if one can't be created.  Given one of these pools, pci_pool_alloc()
67  * may be used to allocate memory.  Such memory will all have "consistent"
68  * DMA mappings, accessible by the device and its driver without using
69  * cache flushing primitives.  The actual size of blocks allocated may be
70  * larger than requested because of alignment.
71  *
72  * If allocation is nonzero, objects returned from pci_pool_alloc() won't
73  * cross that size boundary.  This is useful for devices which have
74  * addressing restrictions on individual DMA transfers, such as not crossing
75  * boundaries of 4KBytes.
76  */
77 struct pci_pool *
78 pci_pool_create (const char *name, struct pci_dev *pdev,
79         size_t size, size_t align, size_t allocation, int flags)
80 {
81         struct pci_pool         *retval;
82
83         if (align == 0)
84                 align = 1;
85         if (size == 0)
86                 return 0;
87         else if (size < align)
88                 size = align;
89         else if ((size % align) != 0) {
90                 size += align + 1;
91                 size &= ~(align - 1);
92         }
93
94         if (allocation == 0) {
95                 if (PAGE_SIZE < size)
96                         allocation = size;
97                 else
98                         allocation = PAGE_SIZE;
99                 // FIXME: round up for less fragmentation
100         } else if (allocation < size)
101                 return 0;
102
103         if (!(retval = kmalloc (sizeof *retval, flags)))
104                 return retval;
105
106 #ifdef  CONFIG_PCIPOOL_DEBUG
107         flags |= SLAB_POISON;
108 #endif
109
110         strncpy (retval->name, name, sizeof retval->name);
111         retval->name [sizeof retval->name - 1] = 0;
112
113         retval->dev = pdev;
114         INIT_LIST_HEAD (&retval->page_list);
115         spin_lock_init (&retval->lock);
116         retval->size = size;
117         retval->flags = flags;
118         retval->allocation = allocation;
119         retval->blocks_per_page = allocation / size;
120         init_waitqueue_head (&retval->waitq);
121
122 #ifdef CONFIG_PCIPOOL_DEBUG
123         printk (KERN_DEBUG "pcipool create %s/%s size %d, %d/page (%d alloc)\n",
124                 pdev ? pdev->slot_name : NULL, retval->name, size,
125                 retval->blocks_per_page, allocation);
126 #endif
127
128         return retval;
129 }
130
131
132 static struct pci_page *
133 pool_alloc_page (struct pci_pool *pool, int mem_flags)
134 {
135         struct pci_page *page;
136         int             mapsize;
137
138         mapsize = pool->blocks_per_page;
139         mapsize = (mapsize + BITS_PER_LONG - 1) / BITS_PER_LONG;
140         mapsize *= sizeof (long);
141
142         page = (struct pci_page *) kmalloc (mapsize + sizeof *page, mem_flags);
143         if (!page)
144                 return 0;
145         page->vaddr = pci_alloc_consistent (pool->dev,
146                                 pool->allocation, &page->dma);
147         if (page->vaddr) {
148                 memset (page->bitmap, 0xff, mapsize);   // bit set == free
149                 if (pool->flags & SLAB_POISON)
150                         memset (page->vaddr, POOL_POISON_BYTE, pool->allocation);
151                 list_add (&page->page_list, &pool->page_list);
152         } else {
153                 kfree (page);
154                 page = 0;
155         }
156         return page;
157 }
158
159
160 static inline int
161 is_page_busy (int blocks, unsigned long *bitmap)
162 {
163         while (blocks > 0) {
164                 if (*bitmap++ != ~0UL)
165                         return 1;
166                 blocks -= BITS_PER_LONG;
167         }
168         return 0;
169 }
170
171 static void
172 pool_free_page (struct pci_pool *pool, struct pci_page *page)
173 {
174         dma_addr_t      dma = page->dma;
175
176         if (pool->flags & SLAB_POISON)
177                 memset (page->vaddr, POOL_POISON_BYTE, pool->allocation);
178         pci_free_consistent (pool->dev, pool->allocation, page->vaddr, dma);
179         list_del (&page->page_list);
180         kfree (page);
181 }
182
183
184 /**
185  * pci_pool_destroy - destroys a pool of pci memory blocks.
186  * @pool: pci pool that will be destroyed
187  *
188  * Caller guarantees that no more memory from the pool is in use,
189  * and that nothing will try to use the pool after this call.
190  */
191 void
192 pci_pool_destroy (struct pci_pool *pool)
193 {
194         unsigned long           flags;
195
196 #ifdef CONFIG_PCIPOOL_DEBUG
197         printk (KERN_DEBUG "pcipool destroy %s/%s\n",
198                 pool->dev ? pool->dev->slot_name : NULL,
199                 pool->name);
200 #endif
201
202         spin_lock_irqsave (&pool->lock, flags);
203         while (!list_empty (&pool->page_list)) {
204                 struct pci_page         *page;
205                 page = list_entry (pool->page_list.next,
206                                 struct pci_page, page_list);
207                 if (is_page_busy (pool->blocks_per_page, page->bitmap)) {
208                         printk (KERN_ERR "pci_pool_destroy %s/%s, %p busy\n",
209                                 pool->dev ? pool->dev->slot_name : NULL,
210                                 pool->name, page->vaddr);
211                         /* leak the still-in-use consistent memory */
212                         list_del (&page->page_list);
213                         kfree (page);
214                 } else
215                         pool_free_page (pool, page);
216         }
217         spin_unlock_irqrestore (&pool->lock, flags);
218         kfree (pool);
219 }
220
221
222 /**
223  * pci_pool_alloc - get a block of consistent memory
224  * @pool: pci pool that will produce the block
225  * @mem_flags: SLAB_KERNEL or SLAB_ATOMIC
226  * @handle: pointer to dma address of block
227  *
228  * This returns the kernel virtual address of a currently unused block,
229  * and reports its dma address through the handle.
230  * If such a memory block can't be allocated, null is returned.
231  */
232 void *
233 pci_pool_alloc (struct pci_pool *pool, int mem_flags, dma_addr_t *handle)
234 {
235         unsigned long           flags;
236         struct list_head        *entry;
237         struct pci_page         *page;
238         int                     map, block;
239         size_t                  offset;
240         void                    *retval;
241
242 restart:
243         spin_lock_irqsave (&pool->lock, flags);
244         list_for_each (entry, &pool->page_list) {
245                 int             i;
246                 page = list_entry (entry, struct pci_page, page_list);
247                 /* only cachable accesses here ... */
248                 for (map = 0, i = 0;
249                                 i < pool->blocks_per_page;
250                                 i += BITS_PER_LONG, map++) {
251                         if (page->bitmap [map] == 0)
252                                 continue;
253                         block = ffz (~ page->bitmap [map]);
254                         if ((i + block) < pool->blocks_per_page) {
255                                 clear_bit (block, &page->bitmap [map]);
256                                 offset = (BITS_PER_LONG * map) + block;
257                                 offset *= pool->size;
258                                 goto ready;
259                         }
260                 }
261         }
262         if (!(page = pool_alloc_page (pool, mem_flags))) {
263                 if (mem_flags == SLAB_KERNEL) {
264                         DECLARE_WAITQUEUE (wait, current);
265
266                         current->state = TASK_INTERRUPTIBLE;
267                         add_wait_queue (&pool->waitq, &wait);
268                         spin_unlock_irqrestore (&pool->lock, flags);
269
270                         schedule_timeout (POOL_TIMEOUT_JIFFIES);
271
272                         current->state = TASK_RUNNING;
273                         remove_wait_queue (&pool->waitq, &wait);
274                         goto restart;
275                 }
276                 retval = 0;
277                 goto done;
278         }
279
280         clear_bit (0, &page->bitmap [0]);
281         offset = 0;
282 ready:
283         retval = offset + page->vaddr;
284         *handle = offset + page->dma;
285 done:
286         spin_unlock_irqrestore (&pool->lock, flags);
287         return retval;
288 }
289
290
291 static struct pci_page *
292 pool_find_page (struct pci_pool *pool, dma_addr_t dma)
293 {
294         unsigned long           flags;
295         struct list_head        *entry;
296         struct pci_page         *page;
297
298         spin_lock_irqsave (&pool->lock, flags);
299         list_for_each (entry, &pool->page_list) {
300                 page = list_entry (entry, struct pci_page, page_list);
301                 if (dma < page->dma)
302                         continue;
303                 if (dma < (page->dma + pool->allocation))
304                         goto done;
305         }
306         page = 0;
307 done:
308         spin_unlock_irqrestore (&pool->lock, flags);
309         return page;
310 }
311
312
313 /**
314  * pci_pool_free - put block back into pci pool
315  * @pool: the pci pool holding the block
316  * @vaddr: virtual address of block
317  * @dma: dma address of block
318  *
319  * Caller promises neither device nor driver will again touch this block
320  * unless it is first re-allocated.
321  */
322 void
323 pci_pool_free (struct pci_pool *pool, void *vaddr, dma_addr_t dma)
324 {
325         struct pci_page         *page;
326         unsigned long           flags;
327         int                     map, block;
328
329         if ((page = pool_find_page (pool, dma)) == 0) {
330                 printk (KERN_ERR "pci_pool_free %s/%s, %p/%x (bad dma)\n",
331                         pool->dev ? pool->dev->slot_name : NULL,
332                         pool->name, vaddr, dma);
333                 return;
334         }
335 #ifdef  CONFIG_PCIPOOL_DEBUG
336         if (((dma - page->dma) + (void *)page->vaddr) != vaddr) {
337                 printk (KERN_ERR "pci_pool_free %s/%s, %p (bad vaddr)/%x\n",
338                         pool->dev ? pool->dev->slot_name : NULL,
339                         pool->name, vaddr, dma);
340                 return;
341         }
342 #endif
343
344         block = dma - page->dma;
345         block /= pool->size;
346         map = block / BITS_PER_LONG;
347         block %= BITS_PER_LONG;
348
349 #ifdef  CONFIG_PCIPOOL_DEBUG
350         if (page->bitmap [map] & (1UL << block)) {
351                 printk (KERN_ERR "pci_pool_free %s/%s, dma %x already free\n",
352                         pool->dev ? pool->dev->slot_name : NULL,
353                         pool->name, dma);
354                 return;
355         }
356 #endif
357         if (pool->flags & SLAB_POISON)
358                 memset (vaddr, POOL_POISON_BYTE, pool->size);
359
360         spin_lock_irqsave (&pool->lock, flags);
361         set_bit (block, &page->bitmap [map]);
362         if (waitqueue_active (&pool->waitq))
363                 wake_up (&pool->waitq);
364         /*
365          * Resist a temptation to do
366          *    if (!is_page_busy(bpp, page->bitmap)) pool_free_page(pool, page);
367          * it is not interrupt safe. Better have empty pages hang around.
368          */
369         spin_unlock_irqrestore (&pool->lock, flags);
370 }
371
372
373 EXPORT_SYMBOL (pci_pool_create);
374 EXPORT_SYMBOL (pci_pool_destroy);
375 EXPORT_SYMBOL (pci_pool_alloc);
376 EXPORT_SYMBOL (pci_pool_free);
377