aboutsummaryrefslogtreecommitdiffstats
path: root/arch/m68k/amiga
diff options
context:
space:
mode:
Diffstat (limited to 'arch/m68k/amiga')
-rw-r--r--arch/m68k/amiga/chipram.c136
1 files changed, 63 insertions, 73 deletions
diff --git a/arch/m68k/amiga/chipram.c b/arch/m68k/amiga/chipram.c
index dd0447db1c9..99449fbf9a7 100644
--- a/arch/m68k/amiga/chipram.c
+++ b/arch/m68k/amiga/chipram.c
@@ -16,6 +16,7 @@
16#include <linux/string.h> 16#include <linux/string.h>
17#include <linux/module.h> 17#include <linux/module.h>
18 18
19#include <asm/atomic.h>
19#include <asm/page.h> 20#include <asm/page.h>
20#include <asm/amigahw.h> 21#include <asm/amigahw.h>
21 22
@@ -23,111 +24,100 @@ unsigned long amiga_chip_size;
23EXPORT_SYMBOL(amiga_chip_size); 24EXPORT_SYMBOL(amiga_chip_size);
24 25
25static struct resource chipram_res = { 26static struct resource chipram_res = {
26 .name = "Chip RAM", .start = CHIP_PHYSADDR 27 .name = "Chip RAM", .start = CHIP_PHYSADDR
27}; 28};
28static unsigned long chipavail; 29static atomic_t chipavail;
29 30
30 31
31void __init amiga_chip_init(void) 32void __init amiga_chip_init(void)
32{ 33{
33 if (!AMIGAHW_PRESENT(CHIP_RAM)) 34 if (!AMIGAHW_PRESENT(CHIP_RAM))
34 return; 35 return;
35 36
36 chipram_res.end = amiga_chip_size-1; 37 chipram_res.end = CHIP_PHYSADDR + amiga_chip_size - 1;
37 request_resource(&iomem_resource, &chipram_res); 38 request_resource(&iomem_resource, &chipram_res);
38 39
39 chipavail = amiga_chip_size; 40 atomic_set(&chipavail, amiga_chip_size);
40} 41}
41 42
42 43
43void *amiga_chip_alloc(unsigned long size, const char *name) 44void *amiga_chip_alloc(unsigned long size, const char *name)
44{ 45{
45 struct resource *res; 46 struct resource *res;
47 void *p;
46 48
47 /* round up */ 49 res = kzalloc(sizeof(struct resource), GFP_KERNEL);
48 size = PAGE_ALIGN(size); 50 if (!res)
51 return NULL;
49 52
50#ifdef DEBUG 53 res->name = name;
51 printk("amiga_chip_alloc: allocate %ld bytes\n", size); 54 p = amiga_chip_alloc_res(size, res);
52#endif 55 if (!p) {
53 res = kzalloc(sizeof(struct resource), GFP_KERNEL); 56 kfree(res);
54 if (!res) 57 return NULL;
55 return NULL; 58 }
56 res->name = name;
57 59
58 if (allocate_resource(&chipram_res, res, size, 0, UINT_MAX, PAGE_SIZE, NULL, NULL) < 0) { 60 return p;
59 kfree(res);
60 return NULL;
61 }
62 chipavail -= size;
63#ifdef DEBUG
64 printk("amiga_chip_alloc: returning %lx\n", res->start);
65#endif
66 return (void *)ZTWO_VADDR(res->start);
67} 61}
68EXPORT_SYMBOL(amiga_chip_alloc); 62EXPORT_SYMBOL(amiga_chip_alloc);
69 63
70 64
71 /* 65 /*
72 * Warning: 66 * Warning:
73 * amiga_chip_alloc_res is meant only for drivers that need to allocate 67 * amiga_chip_alloc_res is meant only for drivers that need to
74 * Chip RAM before kmalloc() is functional. As a consequence, those 68 * allocate Chip RAM before kmalloc() is functional. As a consequence,
75 * drivers must not free that Chip RAM afterwards. 69 * those drivers must not free that Chip RAM afterwards.
76 */ 70 */
77 71
78void * __init amiga_chip_alloc_res(unsigned long size, struct resource *res) 72void *amiga_chip_alloc_res(unsigned long size, struct resource *res)
79{ 73{
80 unsigned long start; 74 int error;
81 75
82 /* round up */ 76 /* round up */
83 size = PAGE_ALIGN(size); 77 size = PAGE_ALIGN(size);
84 /* dmesg into chipmem prefers memory at the safe end */ 78
85 start = CHIP_PHYSADDR + chipavail - size; 79 pr_debug("amiga_chip_alloc_res: allocate %lu bytes\n", size);
86 80 error = allocate_resource(&chipram_res, res, size, 0, UINT_MAX,
87#ifdef DEBUG 81 PAGE_SIZE, NULL, NULL);
88 printk("amiga_chip_alloc_res: allocate %ld bytes\n", size); 82 if (error < 0) {
89#endif 83 pr_err("amiga_chip_alloc_res: allocate_resource() failed %d!\n",
90 if (allocate_resource(&chipram_res, res, size, start, UINT_MAX, PAGE_SIZE, NULL, NULL) < 0) { 84 error);
91 printk("amiga_chip_alloc_res: first alloc failed!\n"); 85 return NULL;
92 if (allocate_resource(&chipram_res, res, size, 0, UINT_MAX, PAGE_SIZE, NULL, NULL) < 0) 86 }
93 return NULL; 87
94 } 88 atomic_sub(size, &chipavail);
95 chipavail -= size; 89 pr_debug("amiga_chip_alloc_res: returning %pR\n", res);
96#ifdef DEBUG 90 return (void *)ZTWO_VADDR(res->start);
97 printk("amiga_chip_alloc_res: returning %lx\n", res->start);
98#endif
99 return (void *)ZTWO_VADDR(res->start);
100} 91}
101 92
102void amiga_chip_free(void *ptr) 93void amiga_chip_free(void *ptr)
103{ 94{
104 unsigned long start = ZTWO_PADDR(ptr); 95 unsigned long start = ZTWO_PADDR(ptr);
105 struct resource **p, *res; 96 struct resource *res;
106 unsigned long size; 97 unsigned long size;
107 98
108 for (p = &chipram_res.child; (res = *p); p = &res->sibling) { 99 res = lookup_resource(&chipram_res, start);
109 if (res->start != start) 100 if (!res) {
110 continue; 101 pr_err("amiga_chip_free: trying to free nonexistent region at "
111 *p = res->sibling; 102 "%p\n", ptr);
112 size = res->end-start; 103 return;
113#ifdef DEBUG 104 }
114 printk("amiga_chip_free: free %ld bytes at %p\n", size, ptr); 105
115#endif 106 size = resource_size(res);
116 chipavail += size; 107 pr_debug("amiga_chip_free: free %lu bytes at %p\n", size, ptr);
108 atomic_add(size, &chipavail);
109 release_resource(res);
117 kfree(res); 110 kfree(res);
118 return;
119 }
120 printk("amiga_chip_free: trying to free nonexistent region at %p\n", ptr);
121} 111}
122EXPORT_SYMBOL(amiga_chip_free); 112EXPORT_SYMBOL(amiga_chip_free);
123 113
124 114
125unsigned long amiga_chip_avail(void) 115unsigned long amiga_chip_avail(void)
126{ 116{
127#ifdef DEBUG 117 unsigned long n = atomic_read(&chipavail);
128 printk("amiga_chip_avail : %ld bytes\n", chipavail); 118
129#endif 119 pr_debug("amiga_chip_avail : %lu bytes\n", n);
130 return chipavail; 120 return n;
131} 121}
132EXPORT_SYMBOL(amiga_chip_avail); 122EXPORT_SYMBOL(amiga_chip_avail);
133 123