Commit 217bbd81885587b462311fab1b04172926c59f1e

Authored by Michael Schmitz
Committed by Geert Uytterhoeven
1 parent b7785e9543

m68k/atari: Reserve some ST-RAM early on for device buffer use

Based on an original patch from Michael Schmitz:

Because mem_init() is now called before device init, devices that rely on
ST-RAM may find all ST-RAM already allocated to other users by the time
device init happens. In particular, a large initrd RAM disk may use up
enough of ST-RAM to cause atari_stram_alloc() to resort to
__get_dma_pages() allocation.

In the current state of Atari memory management, all of RAM is marked
DMA capable, so __get_dma_pages() may well return RAM that is not in actual
fact DMA capable. Using this for frame buffer or SCSI DMA buffer causes
subtle failure.

The ST-RAM allocator has been changed to allocate memory from a pool of
reserved ST-RAM of configurable size, set aside on ST-RAM init (i.e.
before mem_init()). As long as this pool is not exhausted, allocation of
real ST-RAM can be guaranteed.

Other changes:
  - Replace the custom allocator in the ST-RAM pool by the existing allocator
    in the resource subsystem,
  - Remove mem_init_done and its hook, as memory init is now done before
    device init,
  - Remove /proc/stram, as ST-RAM usage now shows up under /proc/iomem, e.g.

	005f2000-006f1fff : ST-RAM Pool
	  005f2000-0063dfff : atafb
	  0063e000-00641fff : ataflop
	  00642000-00642fff : SCSI

Signed-off-by: Michael Schmitz <schmitz@debian.org>
[Andreas Schwab <schwab@linux-m68k.org>: Use memparse()]
[Geert: Use the resource subsystem instead of a custom allocator]
Signed-off-by: Geert Uytterhoeven <geert@linux-m68k.org>

Showing 4 changed files with 70 additions and 298 deletions Side-by-side Diff

arch/m68k/Kconfig.mmu
... ... @@ -372,12 +372,6 @@
372 372 Include support in the kernel for pcmcia on Amiga 1200 and Amiga
373 373 600. If you intend to use pcmcia cards say Y; otherwise say N.
374 374  
375   -config STRAM_PROC
376   - bool "ST-RAM statistics in /proc"
377   - depends on ATARI
378   - help
379   - Say Y here to report ST-RAM usage statistics in /proc/stram.
380   -
381 375 config HEARTBEAT
382 376 bool "Use power LED as a heartbeat" if AMIGA || APOLLO || ATARI || MAC ||Q40
383 377 default y if !AMIGA && !APOLLO && !ATARI && !MAC && !Q40 && HP300
arch/m68k/atari/stram.c
1 1 /*
2   - * arch/m68k/atari/stram.c: Functions for ST-RAM allocations
  2 + * Functions for ST-RAM allocations
3 3 *
4 4 * Copyright 1994-97 Roman Hodek <Roman.Hodek@informatik.uni-erlangen.de>
5 5 *
6 6  
7 7  
8 8  
9 9  
10 10  
11 11  
12 12  
13 13  
14 14  
15 15  
16 16  
... ... @@ -30,92 +30,36 @@
30 30 #include <asm/atari_stram.h>
31 31 #include <asm/io.h>
32 32  
33   -#undef DEBUG
34 33  
35   -#ifdef DEBUG
36   -#define DPRINTK(fmt,args...) printk( fmt, ##args )
37   -#else
38   -#define DPRINTK(fmt,args...)
39   -#endif
40   -
41   -#if defined(CONFIG_PROC_FS) && defined(CONFIG_STRAM_PROC)
42   -/* abbrev for the && above... */
43   -#define DO_PROC
44   -#include <linux/proc_fs.h>
45   -#include <linux/seq_file.h>
46   -#endif
47   -
48 34 /*
49   - * ++roman:
50   - *
51   - * New version of ST-Ram buffer allocation. Instead of using the
52   - * 1 MB - 4 KB that remain when the ST-Ram chunk starts at $1000
53   - * (1 MB granularity!), such buffers are reserved like this:
54   - *
55   - * - If the kernel resides in ST-Ram anyway, we can take the buffer
56   - * from behind the current kernel data space the normal way
57   - * (incrementing start_mem).
58   - *
59   - * - If the kernel is in TT-Ram, stram_init() initializes start and
60   - * end of the available region. Buffers are allocated from there
61   - * and mem_init() later marks the such used pages as reserved.
62   - * Since each TT-Ram chunk is at least 4 MB in size, I hope there
63   - * won't be an overrun of the ST-Ram region by normal kernel data
64   - * space.
65   - *
66   - * For that, ST-Ram may only be allocated while kernel initialization
67   - * is going on, or exactly: before mem_init() is called. There is also
68   - * no provision now for freeing ST-Ram buffers. It seems that isn't
69   - * really needed.
70   - *
  35 + * The ST-RAM allocator allocates memory from a pool of reserved ST-RAM of
  36 + * configurable size, set aside on ST-RAM init.
  37 + * As long as this pool is not exhausted, allocation of real ST-RAM can be
  38 + * guaranteed.
71 39 */
72 40  
73   -/* Start and end (virtual) of ST-RAM */
74   -static void *stram_start, *stram_end;
75   -
76   -/* set after memory_init() executed and allocations via start_mem aren't
77   - * possible anymore */
78   -static int mem_init_done;
79   -
80 41 /* set if kernel is in ST-RAM */
81 42 static int kernel_in_stram;
82 43  
83   -typedef struct stram_block {
84   - struct stram_block *next;
85   - void *start;
86   - unsigned long size;
87   - unsigned flags;
88   - const char *owner;
89   -} BLOCK;
  44 +static struct resource stram_pool = {
  45 + .name = "ST-RAM Pool"
  46 +};
90 47  
91   -/* values for flags field */
92   -#define BLOCK_FREE 0x01 /* free structure in the BLOCKs pool */
93   -#define BLOCK_KMALLOCED 0x02 /* structure allocated by kmalloc() */
94   -#define BLOCK_GFP 0x08 /* block allocated with __get_dma_pages() */
  48 +static unsigned long pool_size = 1024*1024;
95 49  
96   -/* list of allocated blocks */
97   -static BLOCK *alloc_list;
98 50  
99   -/* We can't always use kmalloc() to allocate BLOCK structures, since
100   - * stram_alloc() can be called rather early. So we need some pool of
101   - * statically allocated structures. 20 of them is more than enough, so in most
102   - * cases we never should need to call kmalloc(). */
103   -#define N_STATIC_BLOCKS 20
104   -static BLOCK static_blocks[N_STATIC_BLOCKS];
  51 +static int __init atari_stram_setup(char *arg)
  52 +{
  53 + if (!MACH_IS_ATARI)
  54 + return 0;
105 55  
106   -/***************************** Prototypes *****************************/
  56 + pool_size = memparse(arg, NULL);
  57 + return 0;
  58 +}
107 59  
108   -static BLOCK *add_region( void *addr, unsigned long size );
109   -static BLOCK *find_region( void *addr );
110   -static int remove_region( BLOCK *block );
  60 +early_param("stram_pool", atari_stram_setup);
111 61  
112   -/************************* End of Prototypes **************************/
113 62  
114   -
115   -/* ------------------------------------------------------------------------ */
116   -/* Public Interface */
117   -/* ------------------------------------------------------------------------ */
118   -
119 63 /*
120 64 * This init function is called very early by atari/config.c
121 65 * It initializes some internal variables needed for stram_alloc()
122 66  
123 67  
124 68  
125 69  
126 70  
... ... @@ -123,25 +67,23 @@
123 67 void __init atari_stram_init(void)
124 68 {
125 69 int i;
  70 + void *stram_start;
126 71  
127   - /* initialize static blocks */
128   - for( i = 0; i < N_STATIC_BLOCKS; ++i )
129   - static_blocks[i].flags = BLOCK_FREE;
130   -
131   - /* determine whether kernel code resides in ST-RAM (then ST-RAM is the
132   - * first memory block at virtual 0x0) */
  72 + /*
  73 + * determine whether kernel code resides in ST-RAM
  74 + * (then ST-RAM is the first memory block at virtual 0x0)
  75 + */
133 76 stram_start = phys_to_virt(0);
134 77 kernel_in_stram = (stram_start == 0);
135 78  
136   - for( i = 0; i < m68k_num_memory; ++i ) {
  79 + for (i = 0; i < m68k_num_memory; ++i) {
137 80 if (m68k_memory[i].addr == 0) {
138   - /* skip first 2kB or page (supervisor-only!) */
139   - stram_end = stram_start + m68k_memory[i].size;
140 81 return;
141 82 }
142 83 }
  84 +
143 85 /* Should never come here! (There is always ST-Ram!) */
144   - panic( "atari_stram_init: no ST-RAM found!" );
  86 + panic("atari_stram_init: no ST-RAM found!");
145 87 }
146 88  
147 89  
148 90  
149 91  
150 92  
151 93  
152 94  
153 95  
154 96  
155 97  
156 98  
157 99  
158 100  
159 101  
160 102  
161 103  
162 104  
... ... @@ -151,227 +93,69 @@
151 93 */
152 94 void __init atari_stram_reserve_pages(void *start_mem)
153 95 {
154   - /* always reserve first page of ST-RAM, the first 2 kB are
155   - * supervisor-only! */
  96 + /*
  97 + * always reserve first page of ST-RAM, the first 2 KiB are
  98 + * supervisor-only!
  99 + */
156 100 if (!kernel_in_stram)
157 101 reserve_bootmem(0, PAGE_SIZE, BOOTMEM_DEFAULT);
158 102  
159   -}
  103 + stram_pool.start = (resource_size_t)alloc_bootmem_low_pages(pool_size);
  104 + stram_pool.end = stram_pool.start + pool_size - 1;
  105 + request_resource(&iomem_resource, &stram_pool);
160 106  
161   -void atari_stram_mem_init_hook (void)
162   -{
163   - mem_init_done = 1;
  107 + pr_debug("atari_stram pool: size = %lu bytes, resource = %pR\n",
  108 + pool_size, &stram_pool);
164 109 }
165 110  
166 111  
167   -/*
168   - * This is main public interface: somehow allocate a ST-RAM block
169   - *
170   - * - If we're before mem_init(), we have to make a static allocation. The
171   - * region is taken in the kernel data area (if the kernel is in ST-RAM) or
172   - * from the start of ST-RAM (if the kernel is in TT-RAM) and added to the
173   - * rsvd_stram_* region. The ST-RAM is somewhere in the middle of kernel
174   - * address space in the latter case.
175   - *
176   - * - If mem_init() already has been called, try with __get_dma_pages().
177   - * This has the disadvantage that it's very hard to get more than 1 page,
178   - * and it is likely to fail :-(
179   - *
180   - */
181   -void *atari_stram_alloc(long size, const char *owner)
  112 +void *atari_stram_alloc(unsigned long size, const char *owner)
182 113 {
183   - void *addr = NULL;
184   - BLOCK *block;
185   - int flags;
  114 + struct resource *res;
  115 + int error;
186 116  
187   - DPRINTK("atari_stram_alloc(size=%08lx,owner=%s)\n", size, owner);
  117 + pr_debug("atari_stram_alloc: allocate %lu bytes\n", size);
188 118  
189   - if (!mem_init_done)
190   - return alloc_bootmem_low(size);
191   - else {
192   - /* After mem_init(): can only resort to __get_dma_pages() */
193   - addr = (void *)__get_dma_pages(GFP_KERNEL, get_order(size));
194   - flags = BLOCK_GFP;
195   - DPRINTK( "atari_stram_alloc: after mem_init, "
196   - "get_pages=%p\n", addr );
197   - }
  119 + /* round up */
  120 + size = PAGE_ALIGN(size);
198 121  
199   - if (addr) {
200   - if (!(block = add_region( addr, size ))) {
201   - /* out of memory for BLOCK structure :-( */
202   - DPRINTK( "atari_stram_alloc: out of mem for BLOCK -- "
203   - "freeing again\n" );
204   - free_pages((unsigned long)addr, get_order(size));
205   - return( NULL );
206   - }
207   - block->owner = owner;
208   - block->flags |= flags;
  122 + res = kzalloc(sizeof(struct resource), GFP_KERNEL);
  123 + if (!res)
  124 + return NULL;
  125 +
  126 + res->name = owner;
  127 + error = allocate_resource(&stram_pool, res, size, 0, UINT_MAX,
  128 + PAGE_SIZE, NULL, NULL);
  129 + if (error < 0) {
  130 + pr_err("atari_stram_alloc: allocate_resource() failed %d!\n",
  131 + error);
  132 + kfree(res);
  133 + return NULL;
209 134 }
210   - return( addr );
  135 +
  136 + pr_debug("atari_stram_alloc: returning %pR\n", res);
  137 + return (void *)res->start;
211 138 }
212 139 EXPORT_SYMBOL(atari_stram_alloc);
213 140  
214   -void atari_stram_free( void *addr )
215 141  
  142 +void atari_stram_free(void *addr)
216 143 {
217   - BLOCK *block;
  144 + unsigned long start = (unsigned long)addr;
  145 + struct resource *res;
  146 + unsigned long size;
218 147  
219   - DPRINTK( "atari_stram_free(addr=%p)\n", addr );
220   -
221   - if (!(block = find_region( addr ))) {
222   - printk( KERN_ERR "Attempt to free non-allocated ST-RAM block at %p "
223   - "from %p\n", addr, __builtin_return_address(0) );
  148 + res = lookup_resource(&stram_pool, start);
  149 + if (!res) {
  150 + pr_err("atari_stram_free: trying to free nonexistent region "
  151 + "at %p\n", addr);
224 152 return;
225 153 }
226   - DPRINTK( "atari_stram_free: found block (%p): size=%08lx, owner=%s, "
227   - "flags=%02x\n", block, block->size, block->owner, block->flags );
228 154  
229   - if (!(block->flags & BLOCK_GFP))
230   - goto fail;
231   -
232   - DPRINTK("atari_stram_free: is kmalloced, order_size=%d\n",
233   - get_order(block->size));
234   - free_pages((unsigned long)addr, get_order(block->size));
235   - remove_region( block );
236   - return;
237   -
238   - fail:
239   - printk( KERN_ERR "atari_stram_free: cannot free block at %p "
240   - "(called from %p)\n", addr, __builtin_return_address(0) );
  155 + size = resource_size(res);
  156 + pr_debug("atari_stram_free: free %lu bytes at %p\n", size, addr);
  157 + release_resource(res);
  158 + kfree(res);
241 159 }
242 160 EXPORT_SYMBOL(atari_stram_free);
243   -
244   -
245   -/* ------------------------------------------------------------------------ */
246   -/* Region Management */
247   -/* ------------------------------------------------------------------------ */
248   -
249   -
250   -/* insert a region into the alloced list (sorted) */
251   -static BLOCK *add_region( void *addr, unsigned long size )
252   -{
253   - BLOCK **p, *n = NULL;
254   - int i;
255   -
256   - for( i = 0; i < N_STATIC_BLOCKS; ++i ) {
257   - if (static_blocks[i].flags & BLOCK_FREE) {
258   - n = &static_blocks[i];
259   - n->flags = 0;
260   - break;
261   - }
262   - }
263   - if (!n && mem_init_done) {
264   - /* if statics block pool exhausted and we can call kmalloc() already
265   - * (after mem_init()), try that */
266   - n = kmalloc( sizeof(BLOCK), GFP_KERNEL );
267   - if (n)
268   - n->flags = BLOCK_KMALLOCED;
269   - }
270   - if (!n) {
271   - printk( KERN_ERR "Out of memory for ST-RAM descriptor blocks\n" );
272   - return( NULL );
273   - }
274   - n->start = addr;
275   - n->size = size;
276   -
277   - for( p = &alloc_list; *p; p = &((*p)->next) )
278   - if ((*p)->start > addr) break;
279   - n->next = *p;
280   - *p = n;
281   -
282   - return( n );
283   -}
284   -
285   -
286   -/* find a region (by start addr) in the alloced list */
287   -static BLOCK *find_region( void *addr )
288   -{
289   - BLOCK *p;
290   -
291   - for( p = alloc_list; p; p = p->next ) {
292   - if (p->start == addr)
293   - return( p );
294   - if (p->start > addr)
295   - break;
296   - }
297   - return( NULL );
298   -}
299   -
300   -
301   -/* remove a block from the alloced list */
302   -static int remove_region( BLOCK *block )
303   -{
304   - BLOCK **p;
305   -
306   - for( p = &alloc_list; *p; p = &((*p)->next) )
307   - if (*p == block) break;
308   - if (!*p)
309   - return( 0 );
310   -
311   - *p = block->next;
312   - if (block->flags & BLOCK_KMALLOCED)
313   - kfree( block );
314   - else
315   - block->flags |= BLOCK_FREE;
316   - return( 1 );
317   -}
318   -
319   -
320   -
321   -/* ------------------------------------------------------------------------ */
322   -/* /proc statistics file stuff */
323   -/* ------------------------------------------------------------------------ */
324   -
325   -#ifdef DO_PROC
326   -
327   -#define PRINT_PROC(fmt,args...) seq_printf( m, fmt, ##args )
328   -
329   -static int stram_proc_show(struct seq_file *m, void *v)
330   -{
331   - BLOCK *p;
332   -
333   - PRINT_PROC("Total ST-RAM: %8u kB\n",
334   - (stram_end - stram_start) >> 10);
335   - PRINT_PROC( "Allocated regions:\n" );
336   - for( p = alloc_list; p; p = p->next ) {
337   - PRINT_PROC("0x%08lx-0x%08lx: %s (",
338   - virt_to_phys(p->start),
339   - virt_to_phys(p->start+p->size-1),
340   - p->owner);
341   - if (p->flags & BLOCK_GFP)
342   - PRINT_PROC( "page-alloced)\n" );
343   - else
344   - PRINT_PROC( "??)\n" );
345   - }
346   -
347   - return 0;
348   -}
349   -
350   -static int stram_proc_open(struct inode *inode, struct file *file)
351   -{
352   - return single_open(file, stram_proc_show, NULL);
353   -}
354   -
355   -static const struct file_operations stram_proc_fops = {
356   - .open = stram_proc_open,
357   - .read = seq_read,
358   - .llseek = seq_lseek,
359   - .release = single_release,
360   -};
361   -
362   -static int __init proc_stram_init(void)
363   -{
364   - proc_create("stram", 0, NULL, &stram_proc_fops);
365   - return 0;
366   -}
367   -module_init(proc_stram_init);
368   -#endif
369   -
370   -
371   -/*
372   - * Local variables:
373   - * c-indent-level: 4
374   - * tab-width: 4
375   - * End:
376   - */
arch/m68k/include/asm/atari_stram.h
... ... @@ -6,13 +6,12 @@
6 6 */
7 7  
8 8 /* public interface */
9   -void *atari_stram_alloc(long size, const char *owner);
  9 +void *atari_stram_alloc(unsigned long size, const char *owner);
10 10 void atari_stram_free(void *);
11 11  
12 12 /* functions called internally by other parts of the kernel */
13 13 void atari_stram_init(void);
14 14 void atari_stram_reserve_pages(void *start_mem);
15   -void atari_stram_mem_init_hook (void);
16 15  
17 16 #endif /*_M68K_ATARI_STRAM_H */
arch/m68k/mm/init_mm.c
... ... @@ -83,11 +83,6 @@
83 83 int initpages = 0;
84 84 int i;
85 85  
86   -#ifdef CONFIG_ATARI
87   - if (MACH_IS_ATARI)
88   - atari_stram_mem_init_hook();
89   -#endif
90   -
91 86 /* this will put all memory onto the freelists */
92 87 totalram_pages = num_physpages = 0;
93 88 for_each_online_pgdat(pgdat) {