2 * allocator.c -- allocate after high_memory, if available
4 * NOTE: this is different from my previous allocator, the one that
5 * assembles pages, which revealed itself both slow and unreliable.
7 * Copyright (C) 1998 rubini@linux.it (Alessandro Rubini)
9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published by
11 * the Free Software Foundation; either version 2 of the License, or
12 * (at your option) any later version.
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
19 * You should have received a copy of the GNU General Public License
20 * along with this program; if not, write to the Free Software
21 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
26 Date Programmer Description of changes made
27 -------------------------------------------------------------------
28 02-Aug-2002 NJC allocator now steps in 1MB increments, rather
29 than doubling its size each time.
30 Also, allocator_init(u32 *) now returns
31 (in the first arg) the size of the free
32 space. This is no longer consistent with
33 using the allocator as a module, and some changes
34 may be necessary for that purpose. This was
35 designed to work with the DT3155 driver, in
36 stand alone mode only!!!
37 26-Oct-2009 SS Port to 2.6.30 kernel.
48 #include <linux/version.h>
50 #include <linux/sched.h>
51 #include <linux/kernel.h>
53 #include <linux/proc_fs.h>
54 #include <linux/errno.h>
55 #include <linux/types.h>
56 #include <linux/mm.h> /* PAGE_ALIGN() */
58 #include <linux/slab.h>
63 #define ALL_MSG "allocator: "
65 #undef PDEBUG /* undef it, just in case */
68 # define DUMP_LIST() dump_list()
70 /* This one if debugging is on, and kernel space */
71 # define PDEBUG(fmt, args...) printk(KERN_DEBUG ALL_MSG fmt, ## args)
73 /* This one for user space */
74 # define PDEBUG(fmt, args...) fprintf(stderr, fmt, ## args)
77 # define PDEBUG(fmt, args...) /* not debugging: nothing */
79 # define __static static
83 #define PDEBUGG(fmt, args...)
84 /*#define PDEBUGG(fmt, args...) printk( KERN_DEBUG ALL_MSG fmt, ## args)*/
87 int allocator_himem = 1; /* 0 = probe, pos. = megs, neg. = disable */
88 int allocator_step = 1; /* This is the step size in MB */
89 int allocator_probe = 1; /* This is a flag -- 1=probe, 0=don't probe */
91 static unsigned long allocator_buffer; /* physical address */
92 static unsigned long allocator_buffer_size; /* kilobytes */
95 * The allocator keeps a list of DMA areas, so multiple devices
96 * can coexist. The list is kept sorted by address
99 struct allocator_struct {
100 unsigned long address;
102 struct allocator_struct *next;
105 struct allocator_struct *allocator_list;
109 static int dump_list(void)
111 struct allocator_struct *ptr;
113 PDEBUG("Current list:\n");
114 for (ptr = allocator_list; ptr; ptr = ptr->next)
115 PDEBUG("0x%08lx (size %likB)\n", ptr->address, ptr->size>>10);
120 /* ========================================================================
121 * This function is the actual allocator.
123 * If space is available in high memory (as detected at load time), that
124 * one is returned. The return value is a physical address (i.e., it can
125 * be used straight ahead for DMA, but needs remapping for program use).
128 unsigned long allocator_allocate_dma(unsigned long kilobytes, int prio)
130 struct allocator_struct *ptr = allocator_list, *newptr;
131 unsigned long bytes = kilobytes << 10;
133 /* check if high memory is available */
134 if (!allocator_buffer)
137 /* Round it to a multiple of the pagesize */
138 bytes = PAGE_ALIGN(bytes);
139 PDEBUG("request for %li bytes\n", bytes);
141 while (ptr && ptr->next) {
142 if (ptr->next->address - (ptr->address + ptr->size) >= bytes)
143 break; /* enough space */
148 PDEBUG("alloc failed\n");
149 return 0; /* end of list */
151 newptr = kmalloc(sizeof(struct allocator_struct), prio);
155 /* ok, now stick it after ptr */
156 newptr->address = ptr->address + ptr->size;
157 newptr->size = bytes;
158 newptr->next = ptr->next;
162 PDEBUG("returning 0x%08lx\n", newptr->address);
163 return newptr->address;
166 int allocator_free_dma(unsigned long address)
168 struct allocator_struct *ptr = allocator_list, *prev;
170 while (ptr && ptr->next) {
171 if (ptr->next->address == address)
175 /* the one being freed is ptr->next */
176 prev = ptr; ptr = ptr->next;
179 printk(KERN_ERR ALL_MSG
180 "free_dma(0x%08lx) but add. not allocated\n",
184 PDEBUGG("freeing: %08lx (%li) next %08lx\n", ptr->address, ptr->size,
186 prev->next = ptr->next;
193 /* ========================================================================
196 * On cleanup everything is released. If the list is not empty, that a
197 * problem of our clients
199 int allocator_init(u32 *allocator_max)
201 /* check how much free memory is there */
204 unsigned long trial_size = allocator_himem<<20;
205 unsigned long last_trial = 0;
206 unsigned long step = allocator_step<<20;
208 struct allocator_struct *head, *tail;
209 char test_string[] = "0123456789abcde"; /* 16 bytes */
211 PDEBUGG("himem = %i\n", allocator_himem);
212 if (allocator_himem < 0) /* don't even try */
216 trial_size = 1<<20; /* not specified: try one meg */
219 remapped = ioremap(__pa(high_memory), trial_size);
221 PDEBUGG("%li megs failed!\n", trial_size>>20);
224 PDEBUGG("Trying %li megs (at %p, %p)\n", trial_size>>20,
225 (void *)__pa(high_memory), remapped);
226 for (i = last_trial; i < trial_size; i += 16) {
227 strcpy((char *)(remapped)+i, test_string);
228 if (strcmp((char *)(remapped)+i, test_string))
231 iounmap((void *)remapped);
233 last_trial = trial_size;
235 trial_size += step; /* increment, if all went well */
237 PDEBUGG("%li megs copy test failed!\n", trial_size>>20);
240 if (!allocator_probe)
243 PDEBUG("%li megs (%li k, %li b)\n", i>>20, i>>10, i);
244 allocator_buffer_size = i>>10; /* kilobytes */
245 allocator_buffer = __pa(high_memory);
246 if (!allocator_buffer_size) {
247 printk(KERN_WARNING ALL_MSG "no free high memory to use\n");
252 * to simplify things, always have two cells in the list:
253 * the first and the last. This avoids some conditionals and
254 * extra code when allocating and deallocating: we only play
255 * in the middle of the list
257 head = kmalloc(sizeof(struct allocator_struct), GFP_KERNEL);
260 tail = kmalloc(sizeof(struct allocator_struct), GFP_KERNEL);
266 max = allocator_buffer_size<<10;
268 head->size = tail->size = 0;
269 head->address = allocator_buffer;
270 tail->address = allocator_buffer + max;
273 allocator_list = head;
275 /* Back to the user code, in KB */
276 *allocator_max = allocator_buffer_size;
278 return 0; /* ok, ready */
281 void allocator_cleanup(void)
283 struct allocator_struct *ptr, *next;
285 for (ptr = allocator_list; ptr; ptr = next) {
287 PDEBUG("freeing list: 0x%08lx\n", ptr->address);
291 allocator_buffer = 0;
292 allocator_buffer_size = 0;
293 allocator_list = NULL;