From: Geert U. <ge...@li...> - 2000-09-18 16:05:58
|
On Thu, 14 Sep 2000, Geert Uytterhoeven wrote: > On Thu, 14 Sep 2000, Geert Uytterhoeven wrote: > > On Thu, 14 Sep 2000, Geert Uytterhoeven wrote: > > > I'll try to cook an (untested) patch... > > > > Does this sound OK? Please remove the debug code (marked with FIXME) after > > testing. These cases just shouldn't happen. > > Hmmm... since we need the struct resource anyway, perhaps it's even better to > always use the static struct resource. And it doesn't make much sense to have > two types of resource management (struct resource and struct chip_desc), so > I'll remove the latter. Wait and see... So what about this? Now the Chip RAM allocator uses the resource management system to track allocations. Caveat: the patch is untested, but it compiles. I think something similar can be done for zorro_unused_z2ram[], but I don't dare to touch it since I can't test the z2ram driver. Besides, I already expect `Zorro: Address space collision on device ...' messages on systems with Z2 RAM on Zorro expansion cards. --- geert-chipram-2.4.0-test8/include/asm-m68k/amigahw.h.orig Mon Jul 17 15:13:48 2000 +++ geert-chipram-2.4.0-test8/include/asm-m68k/amigahw.h Mon Sep 18 16:31:43 2000 @@ -279,9 +279,12 @@ #define ciab ((*(volatile struct CIA *)(zTwoBase + CIAB_PHYSADDR))) #define CHIP_PHYSADDR (0x000000) -#define chipaddr ((unsigned long)(zTwoBase + CHIP_PHYSADDR)) + void amiga_chip_init (void); -void *amiga_chip_alloc (long size, const char *name); +struct resource; +void *__amiga_chip_alloc (unsigned long size, const char *name, + struct resource *res); +#define amiga_chip_alloc(size, name) __amiga_chip_alloc(size, name, NULL) void amiga_chip_free (void *); unsigned long amiga_chip_avail( void ); /*MILAN*/ --- geert-chipram-2.4.0-test8/arch/ppc/amiga/chipram.c.orig Tue Jul 18 14:08:47 2000 +++ geert-chipram-2.4.0-test8/arch/ppc/amiga/chipram.c Mon Sep 18 17:26:56 2000 @@ -3,181 +3,111 @@ ** ** Modified 03-May-94 by Geert Uytterhoeven <ge...@li...> ** - 64-bit aligned allocations for full AGA compatibility +** +** Rewritten 15/9/2000 by Geert to use resource management */ #include <linux/config.h> #include <linux/types.h> #include <linux/kernel.h> #include <linux/init.h> -#include <linux/zorro.h> +#include <linux/ioport.h> +#include <linux/slab.h> #include <asm/amigahw.h> -struct chip_desc { - unsigned first : 1; - unsigned last : 1; - unsigned alloced : 1; - unsigned length : 24; - long pad; /* We suppose this makes this struct 64 bits long!! */ -}; +unsigned long amiga_chip_size; -#define DP(ptr) ((struct chip_desc *)(ptr)) - -u_long amiga_chip_size; +static struct resource chipram_res = { "Chip RAM", CHIP_PHYSADDR }; static unsigned long chipavail; -static struct resource chipram = { "Chip RAM", 0 }; - -unsigned long amiga_chip_avail( void ) -{ -#ifdef DEBUG - printk("chip_avail : %ld bytes\n",chipavail); -#endif - return chipavail; -} - -void __init amiga_chip_init (void) +void __init amiga_chip_init(void) { - struct chip_desc *dp; - - if (!AMIGAHW_PRESENT(CHIP_RAM)) - return; + if (!AMIGAHW_PRESENT(CHIP_RAM)) + return; #ifndef CONFIG_APUS_FAST_EXCEPT - /* - * Remove the first 4 pages where PPC exception handlers will - * be located. - */ - amiga_chip_size -= 0x4000; + /* + * Remove the first 4 pages where PPC exception handlers will be located + */ + amiga_chip_size -= 0x4000; #endif - chipram.end = amiga_chip_size-1; - request_resource(&iomem_resource, &chipram); - - /* initialize start boundary */ - - dp = DP(chipaddr); - dp->first = 1; - - dp->alloced = 0; - dp->length = amiga_chip_size - 2*sizeof(*dp); - - /* initialize end boundary */ - dp = DP(chipaddr + amiga_chip_size) - 1; - dp->last = 1; - - dp->alloced = 0; - dp->length = amiga_chip_size - 2*sizeof(*dp); - chipavail = dp->length; /*MILAN*/ + chipram_res.end = amiga_chip_size-1; + request_resource(&iomem_resource, &chipram_res); -#ifdef DEBUG - printk ("chipram end boundary is %p, length is %d\n", dp, - dp->length); -#endif + chipavail = amiga_chip_size; } -void *amiga_chip_alloc(long size, const char *name) -{ - /* last chunk */ - struct chip_desc *dp; - void *ptr; - - /* round off */ - size = (size + 7) & ~7; + + /* + * Warning: + * `res' is meant to be non-NULL only for drivers that need to allocate + * Chip RAM before kmalloc() is functional. As a consequence, those + * drivers must not free that Chip RAM afterwards. + */ -#ifdef DEBUG - printk("amiga_chip_alloc: allocate %ld bytes\n", size); -#endif +void *__amiga_chip_alloc(unsigned long size, const char *name, + struct resource *res) +{ + void *ptr; + int kmalloced = 0; - /* - * get pointer to descriptor for last chunk by - * going backwards from end chunk - */ - dp = DP(chipaddr + amiga_chip_size) - 1; - dp = DP((unsigned long)dp - dp->length) - 1; - - while ((dp->alloced || dp->length < size) - && !dp->first) - dp = DP ((unsigned long)dp - dp[-1].length) - 2; - - if (dp->alloced || dp->length < size) { - printk ("no chipmem available for %ld allocation\n", size); - return NULL; - } - - if (dp->length < (size + 2*sizeof(*dp))) { - /* length too small to split; allocate the whole thing */ - dp->alloced = 1; - ptr = (void *)(dp+1); - dp = DP((unsigned long)ptr + dp->length); - dp->alloced = 1; -#ifdef DEBUG - printk ("amiga_chip_alloc: no split\n"); -#endif - } else { - /* split the extent; use the end part */ - long newsize = dp->length - (2*sizeof(*dp) + size); + /* round off */ + size = (size + 7) & ~7; #ifdef DEBUG - printk ("amiga_chip_alloc: splitting %d to %ld\n", dp->length, - newsize); + printk("__amiga_chip_alloc: allocate %ld bytes\n", size); #endif - dp->length = newsize; - dp = DP((unsigned long)(dp+1) + newsize); - dp->first = dp->last = 0; - dp->alloced = 0; - dp->length = newsize; - dp++; - dp->first = dp->last = 0; - dp->alloced = 1; - dp->length = size; - ptr = (void *)(dp+1); - dp = DP((unsigned long)ptr + size); - dp->alloced = 1; - dp->length = size; - } + if (!res) { + if (!(res = kmalloc(sizeof(*res), GFP_KERNEL))) + return NULL; + memset(res, 0, sizeof(*res)); + res->name = name; + kmalloced = 1; + } + if (allocate_resource(&chipram_res, res, size, 0, -1, 8, NULL, NULL) < 0) { + printk("__amiga_chip_alloc: no chipmem available for %ld allocation\n", + size); + if (kmalloced) + kfree(res); + return NULL; + } + ptr = (void *)ZTWO_VADDR(res->start); + chipavail -= size; #ifdef DEBUG - printk ("amiga_chip_alloc: returning %p\n", ptr); + printk("__amiga_chip_alloc: returning %p\n", ptr); #endif - - if ((unsigned long)ptr & 7) - panic("amiga_chip_alloc: alignment violation\n"); - - chipavail -= size + (2*sizeof(*dp)); /*MILAN*/ - - if (!request_mem_region(ZTWO_PADDR(ptr), size, name)) - printk(KERN_WARNING "amiga_chip_alloc: region of size %ld at 0x%08lx " - "is busy\n", size, ZTWO_PADDR(ptr)); - return ptr; } -void amiga_chip_free (void *ptr) + +void amiga_chip_free(void *ptr) { - struct chip_desc *sdp = DP(ptr) - 1, *dp2; - struct chip_desc *edp = DP((unsigned long)ptr + sdp->length); + unsigned long start = ZTWO_PADDR(ptr); + struct resource **p, *res; + unsigned long size; + + for (p = &chipram_res.child; (res = *p); p = &res->sibling) { + if (res->start != start) + continue; + *p = res->sibling; + size = res->end-start; +#ifdef DEBUG + printk("amiga_chip_free: free %ld bytes at %p\n", size, ptr); +#endif + chipavail += size; + kfree(res); + return; + } + printk("amiga_chip_free: trying to free nonexistent region at %p\n", ptr); +} - chipavail += sdp->length + (2* sizeof(sdp)); /*MILAN*/ + +unsigned long amiga_chip_avail(void) +{ #ifdef DEBUG - printk("chip_free: free %ld bytes at %p\n",sdp->length,ptr); + printk("amiga_chip_avail : %ld bytes\n", chipavail); #endif - /* deallocate the chunk */ - sdp->alloced = edp->alloced = 0; - release_mem_region(ZTWO_PADDR(ptr), sdp->length); - - /* check if we should merge with the previous chunk */ - if (!sdp->first && !sdp[-1].alloced) { - dp2 = DP((unsigned long)sdp - sdp[-1].length) - 2; - dp2->length += sdp->length + 2*sizeof(*sdp); - edp->length = dp2->length; - sdp = dp2; - } - - /* check if we should merge with the following chunk */ - if (!edp->last && !edp[1].alloced) { - dp2 = DP((unsigned long)edp + edp[1].length) + 2; - dp2->length += edp->length + 2*sizeof(*sdp); - sdp->length = dp2->length; - edp = dp2; - } + return chipavail; } --- geert-chipram-2.4.0-test8/arch/ppc/amiga/config.c.orig Mon Jul 17 14:57:32 2000 +++ geert-chipram-2.4.0-test8/arch/ppc/amiga/config.c Mon Sep 18 17:16:03 2000 @@ -732,9 +732,12 @@ } } +static struct resource debug_res = { "Debug" }; + static void amiga_savekmsg_init(void) { - savekmsg = (struct savekmsg *)amiga_chip_alloc(SAVEKMSG_MAXMEM); + savekmsg = (struct savekmsg *)__amiga_chip_alloc(SAVEKMSG_MAXMEM, NULL, + &debug_res); savekmsg->magic1 = SAVEKMSG_MAGIC1; savekmsg->magic2 = SAVEKMSG_MAGIC2; savekmsg->magicptr = virt_to_phys(savekmsg); --- geert-chipram-2.4.0-test8/arch/m68k/amiga/chipram.c.orig Tue Jul 18 14:04:31 2000 +++ geert-chipram-2.4.0-test8/arch/m68k/amiga/chipram.c Mon Sep 18 17:26:40 2000 @@ -3,173 +3,104 @@ ** ** Modified 03-May-94 by Geert Uytterhoeven <ge...@li...> ** - 64-bit aligned allocations for full AGA compatibility +** +** Rewritten 15/9/2000 by Geert to use resource management */ #include <linux/types.h> #include <linux/kernel.h> #include <linux/init.h> -#include <linux/zorro.h> +#include <linux/ioport.h> +#include <linux/slab.h> #include <asm/amigahw.h> -struct chip_desc { - unsigned first : 1; - unsigned last : 1; - unsigned alloced : 1; - unsigned length : 24; - long pad; /* We suppose this makes this struct 64 bits long!! */ -}; +unsigned long amiga_chip_size; -#define DP(ptr) ((struct chip_desc *)(ptr)) - -u_long amiga_chip_size; +static struct resource chipram_res = { "Chip RAM", CHIP_PHYSADDR }; static unsigned long chipavail; -static struct resource chipram = { "Chip RAM", 0 }; - -unsigned long amiga_chip_avail( void ) -{ -#ifdef DEBUG - printk("chip_avail : %ld bytes\n",chipavail); -#endif - return chipavail; -} - -void __init amiga_chip_init (void) +void __init amiga_chip_init(void) { - struct chip_desc *dp; + if (!AMIGAHW_PRESENT(CHIP_RAM)) + return; - if (!AMIGAHW_PRESENT(CHIP_RAM)) - return; + chipram_res.end = amiga_chip_size-1; + request_resource(&iomem_resource, &chipram_res); - chipram.end = amiga_chip_size-1; - request_resource(&iomem_resource, &chipram); - - /* initialize start boundary */ - - dp = DP(chipaddr); - dp->first = 1; - - dp->alloced = 0; - dp->length = amiga_chip_size - 2*sizeof(*dp); - - /* initialize end boundary */ - dp = DP(chipaddr + amiga_chip_size) - 1; - dp->last = 1; - - dp->alloced = 0; - dp->length = amiga_chip_size - 2*sizeof(*dp); - chipavail = dp->length; /*MILAN*/ - -#ifdef DEBUG - printk ("chipram end boundary is %p, length is %d\n", dp, - dp->length); -#endif + chipavail = amiga_chip_size; } -void *amiga_chip_alloc(long size, const char *name) -{ - /* last chunk */ - struct chip_desc *dp; - void *ptr; + + /* + * Warning: + * `res' is meant to be non-NULL only for drivers that need to allocate + * Chip RAM before kmalloc() is functional. As a consequence, those + * drivers must not free that Chip RAM afterwards. + */ - /* round off */ - size = (size + 7) & ~7; - -#ifdef DEBUG - printk("amiga_chip_alloc: allocate %ld bytes\n", size); -#endif +void *__amiga_chip_alloc(unsigned long size, const char *name, + struct resource *res) +{ + void *ptr; + int kmalloced = 0; - /* - * get pointer to descriptor for last chunk by - * going backwards from end chunk - */ - dp = DP(chipaddr + amiga_chip_size) - 1; - dp = DP((unsigned long)dp - dp->length) - 1; - - while ((dp->alloced || dp->length < size) - && !dp->first) - dp = DP ((unsigned long)dp - dp[-1].length) - 2; - - if (dp->alloced || dp->length < size) { - printk ("no chipmem available for %ld allocation\n", size); - return NULL; - } - - if (dp->length < (size + 2*sizeof(*dp))) { - /* length too small to split; allocate the whole thing */ - dp->alloced = 1; - ptr = (void *)(dp+1); - dp = DP((unsigned long)ptr + dp->length); - dp->alloced = 1; -#ifdef DEBUG - printk ("amiga_chip_alloc: no split\n"); -#endif - } else { - /* split the extent; use the end part */ - long newsize = dp->length - (2*sizeof(*dp) + size); + /* round off */ + size = (size + 7) & ~7; #ifdef DEBUG - printk ("amiga_chip_alloc: splitting %d to %ld\n", dp->length, - newsize); + printk("__amiga_chip_alloc: allocate %ld bytes\n", size); #endif - dp->length = newsize; - dp = DP((unsigned long)(dp+1) + newsize); - dp->first = dp->last = 0; - dp->alloced = 0; - dp->length = newsize; - dp++; - dp->first = dp->last = 0; - dp->alloced = 1; - dp->length = size; - ptr = (void *)(dp+1); - dp = DP((unsigned long)ptr + size); - dp->alloced = 1; - dp->length = size; - } + if (!res) { + if (!(res = kmalloc(sizeof(*res), GFP_KERNEL))) + return NULL; + memset(res, 0, sizeof(*res)); + res->name = name; + kmalloced = 1; + } + if (allocate_resource(&chipram_res, res, size, 0, -1, 8, NULL, NULL) < 0) { + printk("__amiga_chip_alloc: no chipmem available for %ld allocation\n", + size); + if (kmalloced) + kfree(res); + return NULL; + } + ptr = (void *)ZTWO_VADDR(res->start); + chipavail -= size; #ifdef DEBUG - printk ("amiga_chip_alloc: returning %p\n", ptr); + printk("__amiga_chip_alloc: returning %p\n", ptr); #endif - - if ((unsigned long)ptr & 7) - panic("amiga_chip_alloc: alignment violation\n"); - - chipavail -= size + (2*sizeof(*dp)); /*MILAN*/ - - if (!request_mem_region(ZTWO_PADDR(ptr), size, name)) - printk(KERN_WARNING "amiga_chip_alloc: region of size %ld at 0x%08lx " - "is busy\n", size, ZTWO_PADDR(ptr)); - return ptr; } -void amiga_chip_free (void *ptr) + +void amiga_chip_free(void *ptr) { - struct chip_desc *sdp = DP(ptr) - 1, *dp2; - struct chip_desc *edp = DP((unsigned long)ptr + sdp->length); + unsigned long start = ZTWO_PADDR(ptr); + struct resource **p, *res; + unsigned long size; + + for (p = &chipram_res.child; (res = *p); p = &res->sibling) { + if (res->start != start) + continue; + *p = res->sibling; + size = res->end-start; +#ifdef DEBUG + printk("amiga_chip_free: free %ld bytes at %p\n", size, ptr); +#endif + chipavail += size; + kfree(res); + return; + } + printk("amiga_chip_free: trying to free nonexistent region at %p\n", ptr); +} - chipavail += sdp->length + (2* sizeof(sdp)); /*MILAN*/ + +unsigned long amiga_chip_avail(void) +{ #ifdef DEBUG - printk("chip_free: free %ld bytes at %p\n",sdp->length,ptr); + printk("amiga_chip_avail : %ld bytes\n", chipavail); #endif - /* deallocate the chunk */ - sdp->alloced = edp->alloced = 0; - release_mem_region(ZTWO_PADDR(ptr), sdp->length); - - /* check if we should merge with the previous chunk */ - if (!sdp->first && !sdp[-1].alloced) { - dp2 = DP((unsigned long)sdp - sdp[-1].length) - 2; - dp2->length += sdp->length + 2*sizeof(*sdp); - edp->length = dp2->length; - sdp = dp2; - } - - /* check if we should merge with the following chunk */ - if (!edp->last && !edp[1].alloced) { - dp2 = DP((unsigned long)edp + edp[1].length) + 2; - dp2->length += edp->length + 2*sizeof(*sdp); - sdp->length = dp2->length; - edp = dp2; - } + return chipavail; } --- geert-chipram-2.4.0-test8/arch/m68k/amiga/amisound.c.orig Fri Jul 28 21:19:00 2000 +++ geert-chipram-2.4.0-test8/arch/m68k/amiga/amisound.c Mon Sep 18 16:29:00 2000 @@ -11,6 +11,7 @@ #include <linux/sched.h> #include <linux/timer.h> #include <linux/init.h> +#include <linux/ioport.h> #include <asm/system.h> #include <asm/amigahw.h> @@ -40,9 +41,11 @@ static u_long clock_constant; +static struct resource beep_res = { "Beep" }; + void __init amiga_init_sound(void) { - snd_data = amiga_chip_alloc(sizeof(sine_data), "Beep"); + snd_data = __amiga_chip_alloc(sizeof(sine_data), NULL, &beep_res); if (!snd_data) { printk (KERN_CRIT "amiga init_sound: failed to allocate chipmem\n"); return; --- geert-chipram-2.4.0-test8/arch/m68k/amiga/amiga_ksyms.c.orig Tue Jul 18 14:04:31 2000 +++ geert-chipram-2.4.0-test8/arch/m68k/amiga/amiga_ksyms.c Fri Sep 15 16:34:18 2000 @@ -18,7 +18,7 @@ EXPORT_SYMBOL(amiga_hw_present); EXPORT_SYMBOL(amiga_eclock); EXPORT_SYMBOL(amiga_colorclock); -EXPORT_SYMBOL(amiga_chip_alloc); +EXPORT_SYMBOL(__amiga_chip_alloc); EXPORT_SYMBOL(amiga_chip_free); EXPORT_SYMBOL(amiga_chip_avail); EXPORT_SYMBOL(amiga_chip_size); --- geert-chipram-2.4.0-test8/arch/m68k/amiga/config.c.orig Mon Jul 17 15:13:27 2000 +++ geert-chipram-2.4.0-test8/arch/m68k/amiga/config.c Mon Sep 18 17:16:22 2000 @@ -828,9 +828,12 @@ } } +static struct resource debug_res = { "Debug" }; + static void amiga_savekmsg_init(void) { - savekmsg = (struct savekmsg *)amiga_chip_alloc(SAVEKMSG_MAXMEM, "Debug"); + savekmsg = (struct savekmsg *)__amiga_chip_alloc(SAVEKMSG_MAXMEM, NULL, + &debug_res); savekmsg->magic1 = SAVEKMSG_MAGIC1; savekmsg->magic2 = SAVEKMSG_MAGIC2; savekmsg->magicptr = virt_to_phys(savekmsg); Gr{oetje,eeting}s, Geert -- Geert Uytterhoeven -- There's lots of Linux beyond ia32 -- ge...@li... In personal conversations with technical people, I call myself a hacker. But when I'm talking to journalists I just say "programmer" or something like that. -- Linus Torvalds |