From mboxrd@z Thu Jan 1 00:00:00 1970 From: "Menon, Nishanth" Subject: Bridge issue #3! dma_alloc_coherent causing crash - pm branch Date: Thu, 12 Mar 2009 19:23:49 -0500 Message-ID: <7A436F7769CA33409C6B44B358BFFF0CFF51E360@dlee02.ent.ti.com> Mime-Version: 1.0 Content-Type: text/plain; charset=US-ASCII Content-Transfer-Encoding: 7BIT Return-path: Received: from bear.ext.ti.com ([192.94.94.41]:41611 "EHLO bear.ext.ti.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1750859AbZCMAX5 convert rfc822-to-8bit (ORCPT ); Thu, 12 Mar 2009 20:23:57 -0400 Received: from dlep95.itg.ti.com ([157.170.170.107]) by bear.ext.ti.com (8.13.7/8.13.7) with ESMTP id n2D0Npt3010135 for ; Thu, 12 Mar 2009 19:23:56 -0500 Received: from dlee73.ent.ti.com (localhost [127.0.0.1]) by dlep95.itg.ti.com (8.13.8/8.13.8) with ESMTP id n2D0NpcM010602 for ; Thu, 12 Mar 2009 19:23:51 -0500 (CDT) Content-Language: en-US Sender: linux-omap-owner@vger.kernel.org List-Id: linux-omap@vger.kernel.org To: "linux-omap@vger.kernel.org" Cc: "Kanigeri, Hari" , "Woodruff, Richard" , "Gupta, Ramesh" , "Guzman Lugo, Fernando" , "Lakhani, Amish" Hi Folks, I seem to be having (mis?)fortune of hitting every single roadblock on the way.. After applying patches for list_del and the ioremap, I am attempting to loadup bridge in another (and hopefully the last possible way): insmod ./bridgedriver.ko shm_size=0x400000 phys_mempool_base=0 base_img=/lib/dsp/baseimage.dof to do this I need a large enough dma_alloc_coherent pool. So, I changed CONFIG_FB_OMAP_CONSISTENT_DMA_SIZE=10 from 2 to get myself enough space for the driver to do dma_alloc_coherent. Over some 20-30 iterations, I hit the following crash! I added trace printks to every single dma_alloc_coherent and frees in the bridge driver, and the alloc and frees match - so no obvious leaks or pointer corruptions.. So, I wrote (yet another) dummy driver which allocates and frees the memory in the same order as the bridge does. The dummy driver functions correctly and does not crash after few 100s of iterations even! Now, interestingly at the start of every new iterations, the dummy driver gets the same virtual-physical address pair, but in the case of the bridge driver, the addresses change. I suspect that is a symptom of the problem though I do not know the reason why.. Insights are most welcome.. Details: Codebase: l-o pm branch + gitorious + ioremap patch= http://marc.info/?l=linux-omap&m=123689459826837&w=2 (should be in pm branch soon) + autoload patch = http://marc.info/?l=linux-omap&m=123687157321175&w=2 + list-del patch = http://marc.info/?l=linux-omap&m=123686780114707&w=2 (should be in pm branch soon) Bootargs: console=ttyS0,115200n8 noinitrd ip=dhcp root=/dev/nfs rw nfsroot=128.247.75.1:/home/fs/sdp3430,nolock,wsize=1024,rsize=1024 mem=64M (not that 64M matters in this case) Error: <4>insmod: page allocation failure. order:10, mode:0xd0 insmod: page allocation failure. order:10, mode:0xd0 [] [] (dump_stack+0x0/0x14) (dump_stack+0x0/0x14) from [] from [] (__alloc_pages_internal+0x384/0x39c) (__alloc_pages_internal+0x384/0x39c) [] [] (__alloc_pages_internal+0x0/0x39c) (__alloc_pages_internal+0x0/0x39c) from [] from [] (__dma_alloc+0x170/0x3c4) (__dma_alloc+0x170/0x3c4) [] [] (__dma_alloc+0x0/0x3c4) (__dma_alloc+0x0/0x3c4) from [] from [] (dma_alloc_coherent+0x58/0x64) (dma_alloc_coherent+0x58/0x64) [] [] (dma_alloc_coherent+0x0/0x64) (dma_alloc_coherent+0x0/0x64) from [] from [] (MEM_AllocPhysMem+0xc4/0xe4 [bridgedriver]) (MEM_AllocPhysMem+0xc4/0xe4 [bridgedriver]) r7:c1bfdc5c r7:c1bfdc5c r6:48306a00 r6:48306a00 r5:c48aa000 r5:c48aa000 r4:bf11fe60 r4:bf11fe60 [] [] (MEM_AllocPhysMem+0x0/0xe4 [bridgedriver]) (MEM_AllocPhysMem+0x0/0xe4 [bridgedriver]) from [] from [] (DRV_RequestResources+0x2c0/0) (DRV_RequestResources+0x2c0/0x370 [bridgedriver]) r7:48307000 r7:48307000 r6:48306a00 r6:48306a00 r5:c48aa000 r5:c48aa000 r4:00008000 r4:00008000 [] [] (DRV_RequestResources+0x0/0x370 [bridgedriver]) (DRV_RequestResources+0x0/0x370 [bridgedriver]) from [] from [] (DSP_Init+0x68/0xf0) (DSP_Init+0x68/0xf0 [bridgedriver]) [] [] (DSP_Init+0x0/0xf0 [bridgedriver]) (DSP_Init+0x0/0xf0 [bridgedriver]) from [] from [] (bridge_init+0x38c/0x3f4 [bridgedriver]) (bridge_init+0x38c/0x3f4 [bridgedriver]) r6:bf11f750 r6:bf11f750 r5:1dcd6500 r5:1dcd6500 r4:bf120068 r4:bf120068 [] [] (bridge_init+0x0/0x3f4 [bridgedriver]) (bridge_init+0x0/0x3f4 [bridgedriver]) from [] from [] (do_one_initcall+0x64/0x198) (do_one_initcall+0x64/0x198) r8:c002df28 r8:c002df28 r7:00000000 r7:00000000 r6:4023a000 r6:4023a000 r5:bf11fa00 r5:bf11fa00 r4:c03aa340 r4:c03aa340 [] [] (do_one_initcall+0x0/0x198) (do_one_initcall+0x0/0x198) from [] from [] (sys_init_module+0x98/0x188) (sys_init_module+0x98/0x188) [] [] (sys_init_module+0x0/0x188) (sys_init_module+0x0/0x188) from [] from [] (ret_fast_syscall+0x0/0x2c) (ret_fast_syscall+0x0/0x2c) r7:00000080 r7:00000080 r6:00000000 r6:00000000 r5:0000000b r5:0000000b r4:00000000 r4:00000000 Mem-info: Mem-info: Normal per-cpu: Normal per-cpu: CPU 0: hi: 18, btch: 3 usd: 2 CPU 0: hi: 18, btch: 3 usd: 2 Active_anon:0 active_file:0 inactive_anon:201 inactive_file:25 unevictable:0 dirty:0 writeback:0 unstable:0 free:14210 slab:468 mapped:0 pagetables:31 bounce:0 Active_anon:0 active_file:0 inactive_anon:201 inactive_file:25 unevictable:0 dirty:0 writeback:0 unstable:0 free:14210 slab:468 mapped:0 pagetables:31 bounce:0 Normal free:56840kB min:1016kB low:1268kB high:1524kB active_anon:0kB inactive_anon:804kB active_file:0kB inactive_file:100kB unevictable:0kB present:65024kB pages_scanned:0 allo Normal free:56840kB min:1016kB low:1268kB high:1524kB active_anon:0kB inactive_anon:804kB active_file:0kB inactive_file:100kB unevictable:0kB present:65024kB pages_scanned:0 allo lowmem_reserve[]:lowmem_reserve[]: 0 0 0 0 Normal: Normal: 144*4kB 144*4kB 141*8kB 141*8kB 96*16kB 96*16kB 73*32kB 73*32kB 39*64kB 39*64kB 11*128kB 11*128kB 15*256kB 15*256kB 11*512kB 11*512kB 15*1024kB 15*1024kB 11*2048B = 56840kB 25 total pagecache pages 25 total pagecache pages 0 pages in swap cache 0 pages in swap cache Swap cache stats: add 0, delete 0, find 0/0 Swap cache stats: add 0, delete 0, find 0/0 Free swap = 0kB Free swap = 0kB Total swap = 0kB Total swap = 0kB 16384 pages of RAM 16384 pages of RAM 14301 free pages 14301 free pages 1112 reserved pages 1112 reserved pages 468 slab pages 468 slab pages 26 pages shared 26 pages shared 0 pages swap cached 0 pages swap cached Dummy driver: #include #include #include #include #include struct mem_s { void *vir; u32 phy; u32 size; }; static struct mem_s b[] = { {0, 0, 4194304}, {0, 0, 4096}, {0, 0, 71680}, }; static int try; module_param(try, int, 0); MODULE_PARM_DESC(try, "try=3"); static int rev; module_param(rev, int, 0); MODULE_PARM_DESC(rev, "rev=0"); static int __init dummy_init(void) { int i; if (!try) try = (sizeof(b) / sizeof(struct mem_s)); if (try > (sizeof(b) / sizeof(struct mem_s))) { printk(KERN_ERR "Give me proper try value\n"); return -EINVAL; } for (i = 0; i < try; i++) { b[i].vir = dma_alloc_coherent(NULL, b[i].size, &b[i].phy, GFP_KERNEL); printk(KERN_INFO "alloc[%d] - virt=0x%08X phy=0x%08X size=0x%08X\n", i, (u32) (b[i].vir), b[i].phy, b[i].size); if (b[i].vir == NULL) { printk(KERN_ERR "Allocation failed idx=%d\n", i); /* Free up all the prev allocs */ i--; while (i >= 0) { dma_free_coherent(NULL, b[i].size, b[i].vir, b[i].phy); i--; } return -ENOMEM; } } return 0; } module_init(dummy_init); static void __exit dummy_exit(void) { int i; if (rev) { for (i = try - 1; i > -1; i--) { printk(KERN_INFO "free[%d] - virt=0x%08x phy=0x%08x size=0x%08x\n", i, (u32) b[i].vir, b[i].phy, b[i].size); dma_free_coherent(NULL, b[i].size, b[i].vir, b[i].phy); } } else { for (i = 0; i < try; i++) { printk(KERN_INFO "free[%d] - virt=0x%08x phy=0x%08x size=0x%08x\n", i, (u32) b[i].vir, b[i].phy, b[i].size); dma_free_coherent(NULL, b[i].size, b[i].vir, b[i].phy); } } } module_exit(dummy_exit); MODULE_LICENSE("GPL"); #!/bin/bash slee() { echo "Sleep " #sleep 5 } try=1 r=0 while [ $try -lt 4 ]; do i=0 while [ $i -lt 100 ]; do echo "insmod $i try=$try rev=$r" insmod ./dummy.ko try=$try if [ $? -ne 0 ]; then echo "QUIT IN INSMOD $i" exit 1; fi slee echo "rmmod $i" rmmod dummy if [ $? -ne 0 ]; then echo "QUIT IN RMMOD $i" exit 1; fi i=`expr $i + 1` slee if [ $r -eq 0 ]; then r=1 else r=0 fi done try=$(( $try + 1 )) done Now comparing the physical addresses allocated: Dummy Driver: Insmod: alloc[0] - virt=0xFF427000 phy=0x83C00000 size=0x00400000 alloc[1] - virt=0xFF827000 phy=0x83A45000 size=0x00001000 alloc[2] - virt=0xFF828000 phy=0x83A60000 size=0x00011800 rmmod: free[0] - virt=0xff427000 phy=0x83c00000 size=0x00400000 free[1] - virt=0xff827000 phy=0x83a45000 size=0x00001000 free[2] - virt=0xff828000 phy=0x83a60000 size=0x00011800 [All iterations have the same output] Vs bridgedriver:(prints are generated by modifying drivers/dsp/bridge/services/mem.c insmod DMA_ALLOC_COH:MEM_AllocPhysMem369:virt=ff427000,phy=83c00000,size=4194304 1 DMA_ALLOC_COH:MEM_AllocPhysMem369:virt=ff827000,phy=83b4a000,size=4096 1 DMA_ALLOC_COH:MEM_AllocPhysMem369:virt=ff828000,phy=83360000,size=71680 1 rmmod DMA_ALLOC_FREE:MEM_FreePhysMem578:virt=ff828000,phy=83360000,size=71680 DMA_ALLOC_FREE:MEM_FreePhysMem578:virt=ff827000,phy=83b4a000,size=4096 DMA_ALLOC_FREE:MEM_FreePhysMem578:virt=ff427000,phy=83c00000,size=4194304 insmod DMA_ALLOC_COH:MEM_AllocPhysMem369:virt=ff427000,phy=82400000,size=4194304 1 DMA_ALLOC_COH:MEM_AllocPhysMem369:virt=ff827000,phy=83bf9000,size=4096 1 DMA_ALLOC_COH:MEM_AllocPhysMem369:virt=ff828000,phy=83320000,size=71680 1 rmmmod DMA_ALLOC_FREE:MEM_FreePhysMem578:virt=ff828000,phy=83320000,size=71680 DMA_ALLOC_FREE:MEM_FreePhysMem578:virt=ff827000,phy=83bf9000,size=4096 DMA_ALLOC_FREE:MEM_FreePhysMem578:virt=ff427000,phy=82400000,size=4194304 Regards, Nishanth Menon