[Linux-Xtensa] Re: Audio Driver - applied your git patch, I'm looking into buildingyour config on an LX200...

Piet Delaney pdelaney at tensilica.com
Fri Sep 17 01:20:16 PDT 2010


Piet Delaney wrote:
> Piet Delaney wrote:
>> benn.huang wrote:
>>> Hi Piet:
>>>
>>> I've just push some code modified by truby to the branch
>>> 'Piets_Hack_of_Turbys_Audio_Interface_to_do_something_on_DC233' of the
>>> repo 'kernel/xtensa-2.6.29-smp-chipsbank.git'. It's just to fix a
>>> stack memory access violation issue when using the 'mailDataT' struct.
>>> Very thanks for your help, Piet :)
>> Hi Benn, Truby, et. al:
>>
>> Glad to help out. Your driver is getting further here on the DC233L.
>> I'm Still getting the sleeping in atomic BUG():
>>
>> I should likely fix the apparent bug of not showing a backtrace. I think
>> folks at Emlix fixed that at kernel.org and I should assimilate it.
>>
>> 1st run I didn't what what's going in with you code in the kernel.
>> The application just ran and didn't do anything:
>> --------------------------------------------------------------------------------
>> # ./dsp_test
>> open dsp dev
>> init oss device:3 ok
>>
>> open audio dsp dev
>>
>> request chanw0x0
>>
>>
>> Init chan
>> BUG: sleeping function called from invalid context at mm/slab.c:3061
>> in_atomic(): 0, irqs_disabled(): 3, pid: 80, name: dsp_test
>>
>> Stack: 90220d3e d39f37f0 00000001 d02f1430 d399dc50 d3a0ec70 00000001 d02f1430
>>         d39f0000 00000002 d38ac680 00000000 d38ac680 00000009 d03be020 d39f37b0
>>         90044122 d39f3850 d344c6b4 00060300 00000000 d02f1030 00000000 00000000
>> Call Trace:
>> ----------------------------------------------------------------------------------

I fixed the backtrace:
----------------------------------------------------------------------------------------
[root at DC_C_233L test]# ./dsp_test
open dsp dev
init oss device:3 ok

open audio dsp dev

request chan

Init chan
w0x0
BUG: sleeping function called from invalid context at mm/slab.c:3061
in_atomic(): 0, irqs_disabled(): 3, pid: 81, name: dsp_test

Stack: d3a17bc0 d39b7680 d3a17bc0 00000003 d39b7680 d3a17bd4 d3a17d00 0000001c
        d3a17be0 00000004 d3a17e24 d3a17bd0 90074c71 d3a17c20 d022a5fc 00000bf5
        00000003 00000051 d39b7850 d3a17bf0 90074e21 d3a17c60 d3800080 000080d0
Call Trace:
  [<d000ee8e>] __might_sleep+0xe6/0xe8
  [<d0074c71>] cache_alloc_debugcheck_before+0x21/0x2c
  [<d0074e21>] __kmalloc+0x7d/0xec
  [<d017b789>] kmalloc+0x11/0x18
  [<d017b872>] kzalloc+0x16/0x1c
  [<d017b9b5>] SendPlayChanMail+0xd/0xb4
  [<d017bcd8>] audio_dsp_decode+0x44/0x4c
  [<d017ad3c>] cbm60xx_dsp_write+0xcc/0xe0
  [<d007a070>] vfs_write+0xb0/0xf8
  [<d007a1ec>] sys_write+0x40/0x60
  [<d0002c5c>] system_call+0x40/0x50
  [<d000239d>] _user_exception+0x10f/0x130
---------------------------------------------------------------------------------------------------

I'll try this for now:
----------------------------------------------------------------------------------------------------
234 /*------------------------------------------------------------------*/
235 /**
236  * @fn      SendPlayChanMail
237  * @brief   Send stream data mail to set up stream addr and len\n
238  *          Send control mail to play channel
239  * @param   chan  Pointer to channel struct
240  * @return  0     if success
241  * @return  -1    if fail
242  */
243 /*------------------------------------------------------------------*/
244 static int SendPlayChanMail(channelT *chan)
245 {
246     uint32_t     ret;
247
248 #if 0
249     uint8_t     *buffer = (uint8_t *)kzalloc(SEND_DATA_LEN_MAX, GFP_KERNEL);
250 #else
251     uint8_t     *buffer = (uint8_t *)kzalloc(SEND_DATA_LEN_MAX, GFP_ATOMIC);    /* Piet */
252 #endif
253     if( buffer == NULL ) {
254         return -1;
255     }
----------------------------------------------------------------------------------------------------------

Got another one:
------------------(gdb) where
#0  dump_stack () at arch/xtensa/kernel/traps.c:603
#1  0xd000ee8e in __might_sleep (file=0xd022a5fc "mm/slab.c", line=3061) at kernel/sched.c:8536
#2  0xd0074c71 in cache_alloc_debugcheck_before (cachep=0xd3800080, flags=208) at mm/slab.c:3061
#3  0xd0074e21 in __kmalloc (size=40, flags=208) at mm/slab.c:3415
#4  0xd017bee5 in kmalloc (size=40, flags=208) at include/linux/slab_def.h:55
#5  0xd017be48 in SendMail (mailData=0xd39cc130, dataSize=20 '\024', mailType=2, chanId=0, chanFmt=1) at drivers/media/audio/mailbox.c:83
#6  0xd017ba14 in SendPlayChanMail (chan=0xd389aee8) at drivers/media/audio/audio_dsp.c:269
#7  0xd017bcd8 in audio_dsp_decode (chan_id=0, inp_stream=0xd3a30000 "ÿûÀD", inp_len=61440, outp_stream=0x0, outp_len=0xd3a17e24) at drivers/media/audio/audio_dsp.c:508
#8  0xd017ad3c in cbm60xx_dsp_write (file=0xd39f3b10, buf=0x401b90 "ÿûÀD", count=61440, ppos=0xd3a17ed0) at drivers/media/audio/cbm60xx_dsp.c:708
#9  0xd007a070 in vfs_write (file=0xd39f3b10, buf=0x401b90 "ÿûÀD", count=61440, pos=0xd3a17ed0) at fs/read_write.c:347
#10 0xd007a1ec in sys_write (fd=4, buf=0x401b90 "ÿûÀD", count=61440) at fs/read_write.c:399
#11 0xd0002c5c in system_call () at arch/xtensa/kernel/entry.S:2103
#12 0xd000239d in _user_exception () at arch/xtensa/kernel/entry.S:321
#13 0xc0000001 in ?? ()
(gdb)
---------------------------------

I'll try this:

  60 /*-----------------------------------------------------------------*/
  61 /**
  62  * @fn      SendMail
  63  * @brief   Send mail packet through FIFO
  64  * @param   mailData  Pointer to mail payload
  65  * @param   dataSize  Size of mail payload
  66  * @param   mailType  Mail type
  67  * @param   chanId    Channel index
  68  * @param   chanFmt   Decode or encode stream format
  69  * @return  0         If successed
  70  * @return  -1        If failed
  71  */
  72 /*-----------------------------------------------------------------*/
  73 int SendMail(void *mailData, uint8_t dataSize, uint32_t mailType,
  74              uint32_t chanId, uint32_t chanFmt)
  75 {
  76     uint32_t     i;
  77     uint32_t     len;
  78
  79     mailPacketT *pkt  = NULL;
  80     uint32_t     *data = NULL;
  81
  82     len = sizeof(mailPacketT) + dataSize;
  83 #if 0
  84     pkt = (mailPacketT *)kmalloc(len, GFP_KERNEL);
  85 #else
  86     pkt = (mailPacketT *)kmalloc(len, GFP_ATOMIC);              /* piet */
  87 #endif
-------------------------------------------------------------------------------

Looks like I fixed the bug in pci-dma.c; I just commited it and the fix for backtraces
to work correctly. We'll cherry pick these back to the open version soon.

Here the pci-dma.c fix I just pushed.
------------------------
/*
+ * vaddr is an address within the uncacched memory address range.
+ * It was returned above by dma_alloc_coherent().
+ */
  void dma_free_coherent(struct device *hwdev, size_t size,
  			 void *vaddr, dma_addr_t dma_handle)
  {
-	long addr=(long)vaddr+XCHAL_KSEG_CACHED_VADDR-XCHAL_KSEG_BYPASS_VADDR;
+	unsigned long v_addr = (long) vaddr;
+	unsigned long seg_offset = v_addr - XCHAL_KSEG_BYPASS_VADDR;
+	unsigned long addr = XCHAL_KSEG_CACHED_VADDR + seg_offset;

-	if (addr < 0 || addr >= XCHAL_KSEG_SIZE)
+	if (seg_offset < 0 || seg_offset >= XCHAL_KSEG_SIZE)
  		BUG();

  	free_pages(addr, get_order(size));
--------------------------------------------------------------------------------------

I'll push the two GFP_ATOMIC changes shortly, want to see if there are any more.

-piet



> 
> Here's were dump_stack() is failing with your BUG in __might_sleep():
> ------------------------------------------------------------------------------------------------
> (gdb) where
> #0  dump_stack () at arch/xtensa/kernel/traps.c:588
> #1  0xd000ee56 in __might_sleep (file=0xd022a5fc "mm/slab.c", line=3061) at kernel/sched.c:8536
> #2  0xd0074c39 in cache_alloc_debugcheck_before (cachep=0xd3800080, flags=32976) at mm/slab.c:3061
> #3  0xd0074de9 in __kmalloc (size=40, flags=32976) at mm/slab.c:3415
> #4  0xd017b751 in kmalloc (size=40, flags=32976) at include/linux/slab_def.h:55
> #5  0xd017b83a in kzalloc (size=40, flags=208) at include/linux/slab.h:306
> #6  0xd017b97d in SendPlayChanMail (chan=0xd389aee8) at drivers/media/audio/audio_dsp.c:248
> #7  0xd017bca0 in audio_dsp_decode (chan_id=0, inp_stream=0xd3a30000 "ÿûÀD", inp_len=61440, outp_stream=0x0, outp_len=0xd39f7e24) at drivers/media/audio/audio_dsp.c:504
> #8  0xd017ad04 in cbm60xx_dsp_write (file=0xd38536f0, buf=0x401b90 "ÿûÀD", count=61440, ppos=0xd39f7ed0) at drivers/media/audio/cbm60xx_dsp.c:708
> #9  0xd007a038 in vfs_write (file=0xd38536f0, buf=0x401b90 "ÿûÀD", count=61440, pos=0xd39f7ed0) at fs/read_write.c:347
> #10 0xd007a1b4 in sys_write (fd=4, buf=0x401b90 "ÿûÀD", count=61440) at fs/read_write.c:399
> #11 0xd0002c5c in system_call () at arch/xtensa/kernel/entry.S:2103
> #12 0xd000239d in _user_exception () at arch/xtensa/kernel/entry.S:321
> #13 0xc0000001 in ?? ()
> (gdb)
> ----------------------------------------------------------------------------------------------------
> 
> Looks to me your disabling pre-emption in cbm60xx_dsp_write() with the local_irq_save(flags)
> and then ksalloc() is called with GFP_KERNEL. You have to allocate before disabling
> pre-emption or use a GFP_ without the WAIT bit set, like GFP_ATOMIC which is discouraged
> as it causes the kernel to use it's reserved pages.
> 
> 				include/linux/gfp.h
> -------------------------------------------------------------------------------
> /* GFP_ATOMIC means both !wait (__GFP_WAIT not set) and use emergency pool */
> #define GFP_ATOMIC      (__GFP_HIGH)
> #define GFP_NOIO        (__GFP_WAIT)
> #define GFP_NOFS        (__GFP_WAIT | __GFP_IO)
> #define GFP_KERNEL      (__GFP_WAIT | __GFP_IO | __GFP_FS)
> #define GFP_TEMPORARY   (__GFP_WAIT | __GFP_IO | __GFP_FS | \
>                           __GFP_RECLAIMABLE)
> #define GFP_USER        (__GFP_WAIT | __GFP_IO | __GFP_FS | __GFP_HARDWALL)
> #define GFP_HIGHUSER    (__GFP_WAIT | __GFP_IO | __GFP_FS | __GFP_HARDWALL | \
>                           __GFP_HIGHMEM)
> #define GFP_HIGHUSER_MOVABLE    (__GFP_WAIT | __GFP_IO | __GFP_FS | \
>                                   __GFP_HARDWALL | __GFP_HIGHMEM | \
>                                   __GFP_MOVABLE)
> #define GFP_IOFS        (__GFP_IO | __GFP_FS)
> -----------------------------------------------------------------------------------
> 
> -piet
> 
> 
> 
>> So I tried to kill it with <control-C> and hit a panic, not good:
>> -------------------------------------------------------------------------------------------------------------------------------------
>> (gdb) bt
>> #0  panic (fmt=0xd02236c8 "BUG!") at kernel/panic.c:72
>> #1  0xd00066b9 in dma_free_coherent (hwdev=0x0, size=1638400, vaddr=0xdac00000, dma_handle=46137344) at arch/xtensa/kernel/pci-dma.c:75
>> #2  0xd017c26c in DiscardAudioBuf (s=0xdb9ea000) at drivers/media/audio/buffer.c:123
>> #3  0xd017aa6d in cbm60xx_dsp_release (inode=0xd344fa00, filp=0xd39a2ce0) at drivers/media/audio/cbm60xx_dsp.c:416
>> #4  0xd007b441 in __fput (file=0xd39a2ce0) at fs/file_table.c:280
>> #5  0xd007b2c6 in fput (file=0xd39a2ce0) at fs/file_table.c:226
>> #6  0xd00792e2 in filp_close (filp=0xd39a2ce0, id=0xd3816c40) at fs/open.c:1107
>> #7  0xd0014ccf in close_files (files=0xd3816c40) at kernel/exit.c:502
>> #8  0xd0014ddc in put_files_struct (files=0xd3816c40) at kernel/exit.c:530
>> #9  0xd0014e81 in exit_files (tsk=0xd39cd040) at kernel/exit.c:564
>> #10 0xd001580c in do_exit (code=2) at kernel/exit.c:1079
>> #11 0xd0015ad5 in do_group_exit (exit_code=2) at kernel/exit.c:1179
>> #12 0xd0021afc in get_signal_to_deliver (info=0xd39f3e50, return_ka=0xd39f3ed0, regs=0xd39f3f30, cookie=0x0) at kernel/signal.c:1902
>> #13 0xd00057e4 in do_signal (regs=0xd39f3f30, oldset=0xd39cd274) at arch/xtensa/kernel/signal.c:524
>> #14 0xd00023ad in _user_exception () at arch/xtensa/kernel/entry.S:342
>> #15 0xc0000001 in ?? ()
>> (gdb)
>> -------------------------------------------------------------------------------------------
>>
>> The panic is due to the address being > XCHAL_KSEG_SIZE:
>>
>>    9 void dma_free_coherent(struct device *hwdev, size_t size,
>>    70                          void *vaddr, dma_addr_t dma_handle)
>>    71 {
>>    72         long addr=(long)vaddr+XCHAL_KSEG_CACHED_VADDR-XCHAL_KSEG_BYPASS_VADDR;
>>    73
>>    74         if (addr < 0 || addr >= XCHAL_KSEG_SIZE)
>>    75                 BUG();
>>    76
>>    77         free_pages(addr, get_order(size));
>>    78 }
>>
>> Looks like dma_alloc_coherent() allocated a page in the kernel in
>> the 0XD000,0000 to 0xD7FFF,FFFF range and returns it in the range
>> 0xd8000000 to 0xDFFFF,FFFF.
>>
>> This function does the reverse mapping. So you address coming in
>> vaddr at 0xdac00000 looks correct. And the address that it mapped
>> to looks right, 0xd2c00000. It looks like the BUG() logic is wrong
>> and should be:
>>
>> 	long seg_offset = (long)vaddr - XCHAL_KSEG_BYPASS_VADDR;
>> 	long addr = CHAL_KSEG_CACHED_VADDR + seg_offset;
>>
>> 	if (seg_offset < 0 || seg_offset >= XCHAL_KSEG_SIZE)
>> 		BUG()'
>>
>> 	free_pages(addr, get_order(size));
>>
>> I'll try changing it and see how that works. Sound right to you
>> guys?
>>
>> Looks like your no longer setting CPENABLE in buffer.c
>> and allowing the kernel generic code to set the 0x80
>> bit on your task's first access. Looks better to me.
>>
>> Are you still seeing the (CPENABLE & 0x80) changing
>> once you have been given access to the I/O port by
>> the exception handler?
>>
>> This current approach with dma_alloc_coherent()
>> and dma_free_coherent() isn't likely optimal
>> with the new V3 MMU.
>>
>> XCHAL_KSEG_SIZE of 0x08000000 (2 GB) is fine but
>> tying up TLB entries permanently for them might be
>> a bit silly. Might be best to allocate some of the
>> physical memory to ZONE DMA and the rest to ZONE_NORMAL
>> and only double map the ZONE_DMA region.
>>
>>
>> -piet
>>
>>
>>> On Thu, 16 Sep 2010 02:29:00 -0700
>>> Piet Delaney <pdelaney at tensilica.com> wrote:
>>>
>>>> benn.huang wrote:
>>>>> Hi, Piet:
>>>>>
>>>>>    the dma_alloc_coherent function has been changed on our platform,
>>>>>    you can try the following patch to fix the memory allocation
>>>>> issue. (just comment out the if statement of the function)
>>>> You guys seem pretty quite. It's 2:30am out here,
>>>> seems like a good time to quite for the evening
>>>> unless you have a bug fix you want to push shortly.
>>>>
>>>> -piet
>>>>
>>>>
>>>>
>>
> 



More information about the linux-xtensa mailing list