Okay, I have got a bit further on the kmalloc failure problem.
I found a discussion about ZONE_DMA in memory:
http://www.mail-archive.com/[email protected]/msg03735.html
which discusses allocation of a ZONE_DMA region for kmalloc(x, GFP_DMA)
calls. If this zone is not setup, then kmalloc will fail with a 0x0
result -- like I am getting. And also from what I gather, it is
necessary to reserve an area for DMA operations so that memory is
flagged to not be cached which would otherwise cause stale data to be
retrieved when accessed from the DMA. In this thread there did not seem
to be a resolution of how to setup the DMA memory zone.
I have been trying to tweak arch/m68knommu/mm/init.c to reserve 1MB for
ZONE_DMA. See my mods to paging_init(void) below.. But this now
results in a new error at bootup (below).
What is the correct way to add a DMA ZONE??
---------boot error output-------
...
ColdFire internal FEC driver version 0.11a (1)
FEC init - kmalloc size 24335 bytes
swapper: page allocation failure. order:3, mode:0x4001
Stack from 00267ef4:
00267f04 00041d22 00042918 00111293 00266d34 00000003 00004001
0011d0f4
00000010 00000003 00000001 00000000 00000000 002506e0 00250dd0
002506d0
001f68b0 00000000 00024001 00267000 00267008 000bd0cc 00049934
00004001
00000003 0011d0f4 00002004 00000b00 edb88303 000000d0 00000010
00000001
0002884e 000496ba 00096424 00267000 00267fd0 000496ea 001f68b0
00000001
00000000 00133be2 001f68b0 00000001 00000000 001369c4 0002884e
00267000
Call
Trace:
[<00020178>] [<000200e2>]
[<00020d3e>]
Mem-info:
DMA per-cpu:
CPU 0: Hot: hi: 0, btch: 1 usd: 0 Cold: hi: 0, btch: 1
usd: 0
Normal
per-cpu:
CPU 0: Hot: hi: 0, btch: 1 usd: 0 Cold: hi: 0, btch: 1
usd: 0
Active:0 inactive:0 dirty:0 writeback:0 unstable:0 free:7365 slab:221
mapped:0 pagetables:0
DMA free:0kB min:20kB low:24kB high:28kB active:0kB inactive:0kB
present:1016kB pages_scanned:0 all_unreclaimable?
no
lowmem_reserve[]: 0
31
Normal free:29460kB min:708kB low:884kB high:1060kB active:0kB
inactive:0kB present:32512kB pages_scanned:0 all_unreclaimable?
no
lowmem_reserve[]: 0
0
DMA: 0*4kB 0*8kB 0*16kB 0*32kB 0*64kB 0*128kB 0*256kB 0*512kB 0*1024kB
0*2048kB 0*4096kB = 0kB
Normal: 1*4kB 0*8kB 1*16kB 0*32kB 0*64kB 0*128kB 1*256kB 1*512kB
0*1024kB 0*2048kB 7*4096kB = 29460kB
8192 pages of
RAM
7366 free
pages
590 reserved
pages
0 pages
shared
0 pages swap
cached
FEC init - kmalloc result 0x0
...
---------boot output-------
Here are my mods of mm/init.c with changes marked by "//DM:..." comments:
void paging_init(void)
{
// DM: add the desired size of dma to reserve.
unsigned int dma_sz = (1*1024*1024) & PAGE_MASK;
/*
* Make sure start_mem is page aligned, otherwise bootmem and
* page_alloc get different views of the world.
*/
#ifdef DEBUG
unsigned long start_mem = PAGE_ALIGN(memory_start);
#endif
unsigned long end_mem = memory_end & PAGE_MASK;
#ifdef DEBUG
printk (KERN_DEBUG "start_mem is %#lx\nvirtual_end is %#lx\n",
start_mem, end_mem);
#endif
/*
* Initialize the bad page table and bad page to point
* to a couple of allocated pages.
*/
empty_bad_page_table = (unsigned long)alloc_bootmem_pages(PAGE_SIZE);
empty_bad_page = (unsigned long)alloc_bootmem_pages(PAGE_SIZE);
empty_zero_page = (unsigned long)alloc_bootmem_pages(PAGE_SIZE);
memset((void *)empty_zero_page, 0, PAGE_SIZE);
/*
* Set up SFC/DFC registers (user data space).
*/
set_fs (USER_DS);
#ifdef DEBUG
printk (KERN_DEBUG "before free_area_init\n");
printk (KERN_DEBUG "free_area_init -> start_mem is %#lx\nvirtual_end
is %#lx\n",
start_mem, end_mem);
#endif
{
unsigned long zones_size[MAX_NR_ZONES] = {0, };
// DM: set the size of dma to reserve in the zones array.
zones_size[ZONE_DMA] = dma_sz >> PAGE_SHIFT; // get num of pages
// DM: set the size of normal zone less the dma size.
zones_size[ZONE_NORMAL] = ((end_mem - PAGE_OFFSET ) >> PAGE_SHIFT)
- zones_size[ZONE_DMA];
#ifdef CONFIG_HIGHMEM
zones_size[ZONE_HIGHMEM] = 0;
#endif
free_area_init(zones_size);
}
}
Dave Meador wrote:
> Hi Greg,
>
> I noticed that the kmalloc call uses the GFP_DMA flag. I am not sure if
> that is a problem. FYI, I have also attempted to implemented DMA for
> use with the FEC driver as the driver hooks into DMA interrupts for
> callbacks when send/receive events occur. I don't know for certain that
> the DMA is working yet, but I do know that the dma init routine is
> called before the FEC init routine.
>
> Here is a snippet of the function where kmalloc fails:
>
> int __init fec_init(void)
> {
> unsigned long offset;
> printk("ColdFire internal FEC driver version %s\n", VERSION);
> memset(&fec_priv_fec0, 0, sizeof (struct fec_priv));
> #ifdef FEC_2
> memset(&fec_priv_fec1, 0, sizeof (struct fec_priv));
> #endif
> // -------- Memory allocation--------
> printk("FEC init - kmalloc size %d bytes\n", FEC_RX_BUF_NUMBER *
> FEC_MAXBUF_SIZE + 15);
> fec_rxbuf_fec0 = kmalloc(FEC_RX_BUF_NUMBER * FEC_MAXBUF_SIZE + 15,
> GFP_DMA);
> printk("FEC init - kmalloc result 0x%X\n", (unsigned int)fec_rxbuf_fec0);
> if (!fec_rxbuf_fec0)
> return -ENOMEM;
> ...
> ...
>
> Greg Ungerer wrote:
>
>> Hi Dave,
>>
>> Dave Meador wrote:
>>
>>> kmalloc is returning 0 when I try to allocate 24335 bytes inside a FEC
>>> driver that I am porting to coldfire uclinux 547x. I have enabled the
>>> kernel feature "[*] Allow allocating large blocks (> 1MB) of memory" to
>>> see if this fixes my problem, but no joy.
>>>
>>> Does anyone have an idea of what I can do to get past this?
>>>
>> Can you show the code?
>>
>> Regards
>> Greg
>>
>>
>>> Here is a snippet of my kernel output when loading:
>>> ...
>>> ColdFire internal UART serial driver
>>> ttyS0 at MMIO 0x10008600 (irq = 99) is a ColdFire UART
>>> ttyS1 at MMIO 0x10008700 (irq = 100) is a ColdFire UART
>>> ttyS2 at MMIO 0x10008800 (irq = 101) is a ColdFire UART
>>> RAMDISK driver initialized: 1 RAM disks of 2048K size 1024 blocksize
>>> loop: loaded (max 8 devices)
>>> ColdFire internal FEC driver version 0.11a
>>> FEC init - kmalloc request size 24335
>>> bytes FEC init - kmalloc result
>>> 0x0 ...
>>> _______________________________________________
>>> uClinux-dev mailing list
>>> [email protected]
>>> http://mailman.uclinux.org/mailman/listinfo/uclinux-dev
>>> This message was resent by [email protected]
>>> To unsubscribe see:
>>> http://mailman.uclinux.org/mailman/options/uclinux-dev
>>>
>>>
> _______________________________________________
> uClinux-dev mailing list
> [email protected]
> http://mailman.uclinux.org/mailman/listinfo/uclinux-dev
> This message was resent by [email protected]
> To unsubscribe see:
> http://mailman.uclinux.org/mailman/options/uclinux-dev
>
_______________________________________________
uClinux-dev mailing list
[email protected]
http://mailman.uclinux.org/mailman/listinfo/uclinux-dev
This message was resent by [email protected]
To unsubscribe see:
http://mailman.uclinux.org/mailman/options/uclinux-dev