[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:37:41 PDT 2010


Piet Delaney wrote:

I committed and pushed the two hacks to calls to zmalloc() to use GFP_ATOMIC.
Your application now starts and can be killed with <Control-c>.
I'm not seeing any mention or problems with CPENABLE being wrong
and my test with tcp_sendmsg() indicated that it's working as I explained
in e-mail and the code.

Are you ok with the current approach?

I've been thinking about extending it to provide separate
contexts for kernel and user space. This would allow TIE
registers to be used in the kernel in addition to TIE I/O
ports and allow ports to be only available to the kernel,
if configured. Still thinking about it, just wondering about
your thoughts on how to handle coprocessors and I/O ports.

Here's what your application looks like:
----------------------------------------------------------
Welcome to your custom Xtensa DC_C_233L_lx200 Developemnt System
DC_C_233L login: root
Password:
[root at DC_C_233L ~]#
[root at DC_C_233L ~]#
[root at DC_C_233L ~]#
[root at DC_C_233L ~]# mount /home/default
[root at DC_C_233L ~]# cd /home/default/
[root at DC_C_233L default]# ls
Audio_Tests/                    hifitest/
Chipbanks/                      mplayer_packages/
HrTimers/                       save_root_files*
LTP_Test/                       saved_root_files/
Music/                          saved_root_files.tar
SSH_Keys                        saved_root_files.tar.prev
Tests/                          saved_root_files.tar.prev.prev
crash-utility/                  swap/
eembc_consumer_noTie_cjpeg/
[root at DC_C_233L default]# cd Chipbanks/test/
[root at DC_C_233L test]# ls
Makefile            dsp_test*           kungfu_mp3.h
cbm60xx_dsp.h       dsp_test.c          mp3_stream.h
cbm60xx_dsp.h.Orig  dsp_test.c.Orig
[root at DC_C_233L test]# ./dsp_test
open dsp dev
init oss device:3 ok

open audio dsp dev

request chanw0x0


Init chan


 <Control-C>
[root at DC_C_233L test]#
[root at DC_C_233L test]#
[root at DC_C_233L test]#
  CTRL-A Z for help | 38400 8N1 | NOR | Minicom 2.3    | VT102 | Online 03:05
------------------------------------------------------------------------------------

-piet

> 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