Commit 22f4bb68 authored by Manuel Lauss's avatar Manuel Lauss Committed by Ralf Baechle

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: default avatarManuel 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: default avatarRalf Baechle <ralf@linux-mips.org>
parent be8cde8b
...@@ -412,8 +412,11 @@ u32 au1xxx_dbdma_ring_alloc(u32 chanid, int entries) ...@@ -412,8 +412,11 @@ u32 au1xxx_dbdma_ring_alloc(u32 chanid, int entries)
if (desc_base == 0) if (desc_base == 0)
return 0; return 0;
ctp->cdb_membase = desc_base;
desc_base = ALIGN_ADDR(desc_base, sizeof(au1x_ddma_desc_t)); desc_base = ALIGN_ADDR(desc_base, sizeof(au1x_ddma_desc_t));
} } else
ctp->cdb_membase = desc_base;
dp = (au1x_ddma_desc_t *)desc_base; dp = (au1x_ddma_desc_t *)desc_base;
/* Keep track of the base descriptor. */ /* Keep track of the base descriptor. */
...@@ -831,7 +834,7 @@ void au1xxx_dbdma_chan_free(u32 chanid) ...@@ -831,7 +834,7 @@ void au1xxx_dbdma_chan_free(u32 chanid)
au1xxx_dbdma_stop(chanid); au1xxx_dbdma_stop(chanid);
kfree((void *)ctp->chan_desc_base); kfree((void *)ctp->cdb_membase);
stp->dev_flags &= ~DEV_FLAGS_INUSE; stp->dev_flags &= ~DEV_FLAGS_INUSE;
dtp->dev_flags &= ~DEV_FLAGS_INUSE; dtp->dev_flags &= ~DEV_FLAGS_INUSE;
......
...@@ -305,6 +305,7 @@ typedef struct dbdma_chan_config { ...@@ -305,6 +305,7 @@ typedef struct dbdma_chan_config {
dbdev_tab_t *chan_dest; dbdev_tab_t *chan_dest;
au1x_dma_chan_t *chan_ptr; au1x_dma_chan_t *chan_ptr;
au1x_ddma_desc_t *chan_desc_base; au1x_ddma_desc_t *chan_desc_base;
u32 cdb_membase; /* kmalloc base of above */
au1x_ddma_desc_t *get_ptr, *put_ptr, *cur_ptr; au1x_ddma_desc_t *get_ptr, *put_ptr, *cur_ptr;
void *chan_callparam; void *chan_callparam;
void (*chan_callback)(int, void *); void (*chan_callback)(int, void *);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment