GUI: Fix Tomato RAF theme for all builds. Compilation typo.
[tomato.git] / release / src-rt-6.x.4708 / linux / linux-2.6.36 / arch / arm / mm / vmregion.c
blob935993e1b1ef53f5372344cbc6a5c764186557b9
1 #include <linux/spinlock.h>
2 #include <linux/list.h>
3 #include <linux/slab.h>
5 #include "vmregion.h"
7 /*
8 * VM region handling support.
10 * This should become something generic, handling VM region allocations for
11 * vmalloc and similar (ioremap, module space, etc).
13 * I envisage vmalloc()'s supporting vm_struct becoming:
15 * struct vm_struct {
16 * struct vmregion region;
17 * unsigned long flags;
18 * struct page **pages;
19 * unsigned int nr_pages;
20 * unsigned long phys_addr;
21 * };
23 * get_vm_area() would then call vmregion_alloc with an appropriate
24 * struct vmregion head (eg):
26 * struct vmregion vmalloc_head = {
27 * .vm_list = LIST_HEAD_INIT(vmalloc_head.vm_list),
28 * .vm_start = VMALLOC_START,
29 * .vm_end = VMALLOC_END,
30 * };
32 * However, vmalloc_head.vm_start is variable (typically, it is dependent on
33 * the amount of RAM found at boot time.) I would imagine that get_vm_area()
34 * would have to initialise this each time prior to calling vmregion_alloc().
37 struct arm_vmregion *
38 arm_vmregion_alloc(struct arm_vmregion_head *head, size_t align,
39 size_t size, gfp_t gfp)
41 unsigned long addr = head->vm_start, end = head->vm_end - size;
42 unsigned long flags;
43 struct arm_vmregion *c, *new;
45 if (head->vm_end - head->vm_start < size) {
46 printk(KERN_WARNING "%s: allocation too big (requested %#x)\n",
47 __func__, size);
48 goto out;
51 new = kmalloc(sizeof(struct arm_vmregion), gfp);
52 if (!new)
53 goto out;
55 spin_lock_irqsave(&head->vm_lock, flags);
57 list_for_each_entry(c, &head->vm_list, vm_list) {
58 if ((addr + size) < addr)
59 goto nospc;
60 if ((addr + size) <= c->vm_start)
61 goto found;
62 addr = ALIGN(c->vm_end, align);
63 if (addr > end)
64 goto nospc;
67 found:
69 * Insert this entry _before_ the one we found.
71 list_add_tail(&new->vm_list, &c->vm_list);
72 new->vm_start = addr;
73 new->vm_end = addr + size;
74 new->vm_active = 1;
76 spin_unlock_irqrestore(&head->vm_lock, flags);
77 return new;
79 nospc:
80 spin_unlock_irqrestore(&head->vm_lock, flags);
81 kfree(new);
82 out:
83 return NULL;
86 static struct arm_vmregion *__arm_vmregion_find(struct arm_vmregion_head *head, unsigned long addr)
88 struct arm_vmregion *c;
90 list_for_each_entry(c, &head->vm_list, vm_list) {
91 if (c->vm_active && c->vm_start == addr)
92 goto out;
94 c = NULL;
95 out:
96 return c;
99 struct arm_vmregion *arm_vmregion_find(struct arm_vmregion_head *head, unsigned long addr)
101 struct arm_vmregion *c;
102 unsigned long flags;
104 spin_lock_irqsave(&head->vm_lock, flags);
105 c = __arm_vmregion_find(head, addr);
106 spin_unlock_irqrestore(&head->vm_lock, flags);
107 return c;
110 struct arm_vmregion *arm_vmregion_find_remove(struct arm_vmregion_head *head, unsigned long addr)
112 struct arm_vmregion *c;
113 unsigned long flags;
115 spin_lock_irqsave(&head->vm_lock, flags);
116 c = __arm_vmregion_find(head, addr);
117 if (c)
118 c->vm_active = 0;
119 spin_unlock_irqrestore(&head->vm_lock, flags);
120 return c;
123 void arm_vmregion_free(struct arm_vmregion_head *head, struct arm_vmregion *c)
125 unsigned long flags;
127 spin_lock_irqsave(&head->vm_lock, flags);
128 list_del(&c->vm_list);
129 spin_unlock_irqrestore(&head->vm_lock, flags);
131 kfree(c);