1 /*
2  * c 2001 PPC 64 Team, IBM Corp
3  *
4  *      This program is free software; you can redistribute it and/or
5  *      modify it under the terms of the GNU General Public License
6  *      as published by the Free Software Foundation; either version
7  *      2 of the License, or (at your option) any later version.
8  */
9 
10 #include <linux/slab.h>
11 #include <linux/vmalloc.h>
12 #include <linux/spinlock.h>
13 
14 #include <asm/uaccess.h>
15 #include <asm/pgalloc.h>
16 
17 rwlock_t imlist_lock = RW_LOCK_UNLOCKED;
18 struct vm_struct * imlist = NULL;
19 
get_im_area(unsigned long size)20 struct vm_struct *get_im_area(unsigned long size)
21 {
22 	unsigned long addr;
23 	struct vm_struct **p, *tmp, *area;
24 
25 	area = (struct vm_struct *) kmalloc(sizeof(*area), GFP_KERNEL);
26 	if (!area)
27 		return NULL;
28 	addr = IMALLOC_START;
29 	write_lock(&imlist_lock);
30 	for (p = &imlist; (tmp = *p) ; p = &tmp->next) {
31 		if (size + addr < (unsigned long) tmp->addr)
32 			break;
33 		addr = tmp->size + (unsigned long) tmp->addr;
34 		if (addr > IMALLOC_END-size) {
35 			write_unlock(&imlist_lock);
36 			kfree(area);
37 			return NULL;
38 		}
39 	}
40 	area->flags = 0;
41 	area->addr = (void *)addr;
42 	area->size = size;
43 	area->next = *p;
44 	*p = area;
45 	write_unlock(&imlist_lock);
46 	return area;
47 }
48 
ifree(void * addr)49 void ifree(void * addr)
50 {
51 	struct vm_struct **p, *tmp;
52 
53 	if (!addr)
54 		return;
55 	if ((PAGE_SIZE-1) & (unsigned long) addr) {
56 		printk(KERN_ERR "Trying to ifree() bad address (%p)\n", addr);
57 		return;
58 	}
59 	write_lock(&imlist_lock);
60 	for (p = &imlist ; (tmp = *p) ; p = &tmp->next) {
61 		if (tmp->addr == addr) {
62 			*p = tmp->next;
63 			kfree(tmp);
64 			write_unlock(&imlist_lock);
65 			return;
66 		}
67 	}
68 	write_unlock(&imlist_lock);
69 	printk(KERN_ERR "Trying to ifree() nonexistent area (%p)\n", addr);
70 }
71 
72