diff options
author | Haavard Skinnemoen <hskinnemoen@atmel.com> | 2007-03-21 11:16:50 -0400 |
---|---|---|
committer | Haavard Skinnemoen <hskinnemoen@atmel.com> | 2007-04-27 07:44:14 -0400 |
commit | f9692b9501c339ec90647d8cd6ee5c106f072f9f (patch) | |
tree | 3a11d55a0383d10cb712b31bc18e57585cdeed4c /arch/avr32/kernel/setup.c | |
parent | d8011768e6bdd0d9de5cc7bdbd3077b4b4fab8c7 (diff) |
[AVR32] Reserve framebuffer memory in early_parse_fbmem()
With the current strategy of using the bootmem allocator to allocate
or reserve framebuffer memory, there's a slight chance that the
requested area has been taken by the boot allocator bitmap before we
get around to reserving it.
By inserting the framebuffer region as a reserved region as early as
possible, we improve our chances for success and we make the region
visible as a reserved region in dmesg and /proc/iomem without any
extra work.
Signed-off-by: Haavard Skinnemoen <hskinnemoen@atmel.com>
Diffstat (limited to 'arch/avr32/kernel/setup.c')
-rw-r--r-- | arch/avr32/kernel/setup.c | 68 |
1 files changed, 61 insertions, 7 deletions
diff --git a/arch/avr32/kernel/setup.c b/arch/avr32/kernel/setup.c index d0a35a1b6a66..1682e2d61cf3 100644 --- a/arch/avr32/kernel/setup.c +++ b/arch/avr32/kernel/setup.c | |||
@@ -191,21 +191,45 @@ find_free_region(const struct resource *mem, resource_size_t size, | |||
191 | return target; | 191 | return target; |
192 | } | 192 | } |
193 | 193 | ||
194 | static int __init | ||
195 | alloc_reserved_region(resource_size_t *start, resource_size_t size, | ||
196 | resource_size_t align, const char *name) | ||
197 | { | ||
198 | struct resource *mem; | ||
199 | resource_size_t target; | ||
200 | int ret; | ||
201 | |||
202 | for (mem = system_ram; mem; mem = mem->sibling) { | ||
203 | target = find_free_region(mem, size, align); | ||
204 | if (target <= mem->end) { | ||
205 | ret = add_reserved_region(target, target + size - 1, | ||
206 | name); | ||
207 | if (!ret) | ||
208 | *start = target; | ||
209 | return ret; | ||
210 | } | ||
211 | } | ||
212 | |||
213 | return -ENOMEM; | ||
214 | } | ||
215 | |||
194 | /* | 216 | /* |
195 | * Early framebuffer allocation. Works as follows: | 217 | * Early framebuffer allocation. Works as follows: |
196 | * - If fbmem_size is zero, nothing will be allocated or reserved. | 218 | * - If fbmem_size is zero, nothing will be allocated or reserved. |
197 | * - If fbmem_start is zero when setup_bootmem() is called, | 219 | * - If fbmem_start is zero when setup_bootmem() is called, |
198 | * fbmem_size bytes will be allocated from the bootmem allocator. | 220 | * a block of fbmem_size bytes will be reserved before bootmem |
221 | * initialization. It will be aligned to the largest page size | ||
222 | * that fbmem_size is a multiple of. | ||
199 | * - If fbmem_start is nonzero, an area of size fbmem_size will be | 223 | * - If fbmem_start is nonzero, an area of size fbmem_size will be |
200 | * reserved at the physical address fbmem_start if necessary. If | 224 | * reserved at the physical address fbmem_start if possible. If |
201 | * the area isn't in a memory region known to the kernel, it will | 225 | * it collides with other reserved memory, a different block of |
202 | * be left alone. | 226 | * same size will be allocated, just as if fbmem_start was zero. |
203 | * | 227 | * |
204 | * Board-specific code may use these variables to set up platform data | 228 | * Board-specific code may use these variables to set up platform data |
205 | * for the framebuffer driver if fbmem_size is nonzero. | 229 | * for the framebuffer driver if fbmem_size is nonzero. |
206 | */ | 230 | */ |
207 | static unsigned long __initdata fbmem_start; | 231 | static resource_size_t __initdata fbmem_start; |
208 | static unsigned long __initdata fbmem_size; | 232 | static resource_size_t __initdata fbmem_size; |
209 | 233 | ||
210 | /* | 234 | /* |
211 | * "fbmem=xxx[kKmM]" allocates the specified amount of boot memory for | 235 | * "fbmem=xxx[kKmM]" allocates the specified amount of boot memory for |
@@ -219,9 +243,39 @@ static unsigned long __initdata fbmem_size; | |||
219 | */ | 243 | */ |
220 | static int __init early_parse_fbmem(char *p) | 244 | static int __init early_parse_fbmem(char *p) |
221 | { | 245 | { |
246 | int ret; | ||
247 | unsigned long align; | ||
248 | |||
222 | fbmem_size = memparse(p, &p); | 249 | fbmem_size = memparse(p, &p); |
223 | if (*p == '@') | 250 | if (*p == '@') { |
224 | fbmem_start = memparse(p, &p); | 251 | fbmem_start = memparse(p, &p); |
252 | ret = add_reserved_region(fbmem_start, | ||
253 | fbmem_start + fbmem_size - 1, | ||
254 | "Framebuffer"); | ||
255 | if (ret) { | ||
256 | printk(KERN_WARNING | ||
257 | "Failed to reserve framebuffer memory\n"); | ||
258 | fbmem_start = 0; | ||
259 | } | ||
260 | } | ||
261 | |||
262 | if (!fbmem_start) { | ||
263 | if ((fbmem_size & 0x000fffffUL) == 0) | ||
264 | align = 0x100000; /* 1 MiB */ | ||
265 | else if ((fbmem_size & 0x0000ffffUL) == 0) | ||
266 | align = 0x10000; /* 64 KiB */ | ||
267 | else | ||
268 | align = 0x1000; /* 4 KiB */ | ||
269 | |||
270 | ret = alloc_reserved_region(&fbmem_start, fbmem_size, | ||
271 | align, "Framebuffer"); | ||
272 | if (ret) { | ||
273 | printk(KERN_WARNING | ||
274 | "Failed to allocate framebuffer memory\n"); | ||
275 | fbmem_size = 0; | ||
276 | } | ||
277 | } | ||
278 | |||
225 | return 0; | 279 | return 0; |
226 | } | 280 | } |
227 | early_param("fbmem", early_parse_fbmem); | 281 | early_param("fbmem", early_parse_fbmem); |