aboutsummaryrefslogtreecommitdiffstats
path: root/arch/mips
diff options
context:
space:
mode:
authorManuel Lauss <manuel.lauss@googlemail.com>2010-01-26 14:39:33 -0500
committerRalf Baechle <ralf@linux-mips.org>2010-02-01 14:30:25 -0500
commit22f4bb68b301f4ab896e9b3b0431fdde962242d2 (patch)
tree62767bbd1ad7d11dbbeea3482b7902f08ea178ce /arch/mips
parentbe8cde8b24c9dca1e54598690115eee5b1476519 (diff)
MIPS: Alchemy: Fix dbdma ring destruction memory debugcheck.
DBDMA descriptors need to be located at 32-byte aligned addresses; however kmalloc in conjunction with the SLAB allocator and CONFIG_DEBUG_SLUB enabled doesn't deliver any. The dbdma code works around that by allocating a larger area and realigning the start address within it. When freeing a channel however this adjustment is not taken into account which results in an oops: Kernel bug detected[#1]: [...] Call Trace: [<80186010>] cache_free_debugcheck+0x284/0x318 [<801869d8>] kfree+0xe8/0x2a0 [<8010b31c>] au1xxx_dbdma_chan_free+0x2c/0x7c [<80388dc8>] au1x_pcm_dbdma_free+0x34/0x4c [<80388fa8>] au1xpsc_pcm_close+0x28/0x38 [<80383cb8>] soc_codec_close+0x14c/0x1cc [<8036dbb4>] snd_pcm_release_substream+0x60/0xac [<8036dc40>] snd_pcm_release+0x40/0xa0 [<8018c7a8>] __fput+0x11c/0x228 [<80188f60>] filp_close+0x7c/0x98 [<80189018>] sys_close+0x9c/0xe4 [<801022a0>] stack_done+0x20/0x3c Fix this by recording the address delivered by kmalloc() and using it as parameter to kfree(). This fix is only necessary with the SLAB allocator and CONFIG_DEBUG_SLAB enabled; non-debug SLAB, SLUB do return nicely aligned addresses, debug-enabled SLUB currently panics early in the boot process. Signed-off-by: Manuel Lauss <manuel.lauss@gmail.com> To: Linux-MIPS <linux-mips@linux-mips.org> Cc: Manuel Lauss <manuel.lauss@gmail.com> Patchwork: http://patchwork.linux-mips.org/patch/878/ Signed-off-by: Ralf Baechle <ralf@linux-mips.org>
Diffstat (limited to 'arch/mips')
-rw-r--r--arch/mips/alchemy/common/dbdma.c7
-rw-r--r--arch/mips/include/asm/mach-au1x00/au1xxx_dbdma.h1
2 files changed, 6 insertions, 2 deletions
diff --git a/arch/mips/alchemy/common/dbdma.c b/arch/mips/alchemy/common/dbdma.c
index 5c68569344c1..f9201ca2295b 100644
--- a/arch/mips/alchemy/common/dbdma.c
+++ b/arch/mips/alchemy/common/dbdma.c
@@ -412,8 +412,11 @@ u32 au1xxx_dbdma_ring_alloc(u32 chanid, int entries)
412 if (desc_base == 0) 412 if (desc_base == 0)
413 return 0; 413 return 0;
414 414
415 ctp->cdb_membase = desc_base;
415 desc_base = ALIGN_ADDR(desc_base, sizeof(au1x_ddma_desc_t)); 416 desc_base = ALIGN_ADDR(desc_base, sizeof(au1x_ddma_desc_t));
416 } 417 } else
418 ctp->cdb_membase = desc_base;
419
417 dp = (au1x_ddma_desc_t *)desc_base; 420 dp = (au1x_ddma_desc_t *)desc_base;
418 421
419 /* Keep track of the base descriptor. */ 422 /* Keep track of the base descriptor. */
@@ -831,7 +834,7 @@ void au1xxx_dbdma_chan_free(u32 chanid)
831 834
832 au1xxx_dbdma_stop(chanid); 835 au1xxx_dbdma_stop(chanid);
833 836
834 kfree((void *)ctp->chan_desc_base); 837 kfree((void *)ctp->cdb_membase);
835 838
836 stp->dev_flags &= ~DEV_FLAGS_INUSE; 839 stp->dev_flags &= ~DEV_FLAGS_INUSE;
837 dtp->dev_flags &= ~DEV_FLAGS_INUSE; 840 dtp->dev_flags &= ~DEV_FLAGS_INUSE;
diff --git a/arch/mips/include/asm/mach-au1x00/au1xxx_dbdma.h b/arch/mips/include/asm/mach-au1x00/au1xxx_dbdma.h
index 06f68f43800a..d206000fbfe2 100644
--- a/arch/mips/include/asm/mach-au1x00/au1xxx_dbdma.h
+++ b/arch/mips/include/asm/mach-au1x00/au1xxx_dbdma.h
@@ -305,6 +305,7 @@ typedef struct dbdma_chan_config {
305 dbdev_tab_t *chan_dest; 305 dbdev_tab_t *chan_dest;
306 au1x_dma_chan_t *chan_ptr; 306 au1x_dma_chan_t *chan_ptr;
307 au1x_ddma_desc_t *chan_desc_base; 307 au1x_ddma_desc_t *chan_desc_base;
308 u32 cdb_membase; /* kmalloc base of above */
308 au1x_ddma_desc_t *get_ptr, *put_ptr, *cur_ptr; 309 au1x_ddma_desc_t *get_ptr, *put_ptr, *cur_ptr;
309 void *chan_callparam; 310 void *chan_callparam;
310 void (*chan_callback)(int, void *); 311 void (*chan_callback)(int, void *);