[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