This patch adds alignment for cache operation address in r4k_dma_cache_inv(). The following oops is fixed by it. Unhandled kernel unaligned access or invalid instruction[#1]: Cpu 0 $ 0 : 00000000 9000c400 8f9a9fff 803e0000 $ 4 : 8f9a9000 00001000 00000001 00000002 $ 8 : 00000000 00000000 8f998084 8f986600 $12 : 00000000 00000000 00000008 00000008 $16 : 8f9a9000 8f9a3500 00000000 00000001 $20 : 00000002 803e0000 803d0000 00000000 $24 : 00000000 80240000 $28 : 8f81a000 8f81b708 803d0000 8009560c Hi : 10623d20 Lo : 4fdf2cc8 epc : 80098470 r4k_dma_cache_inv+0x28/0x64 Not tainted ra : 8009560c dma_map_sg+0xf8/0x14c Status: 9000c402 KERNEL EXL Cause : 00800010 BadVA : 8f9a9fff PrId : 000028a0 (Nevada) Modules linked in: Process swapper (pid: 1, threadinfo=8f81a000, task=8f820000, tls=00000000) Stack : 8f967424 8f967510 8f9a03ee 8f99e140 8f999300 8f998074 8f998000 00000003 803e0000 80253a38 8f967424 8f967510 80370000 8024e344 00000000 8f9a3580 00000008 8f81b770 8f998074 8f99e140 802389fc 8f999458 8f998000 80253a38 80253db4 80253cbc 800df150 00000000 80257af8 8f9a0360 8f99e140 9000c401 8f9a0360 8f99e140 8f986600 8f9674a8 802391ac 8f81b844 8f967400 80224788 ... Call Trace: [<80098470>] r4k_dma_cache_inv+0x28/0x64 [<8009560c>] dma_map_sg+0xf8/0x14c [<8024e344>] ata_qc_issue+0x1ec/0x308 [<80253db4>] ata_scsi_translate+0x134/0x1e8 [<802391ac>] scsi_dispatch_cmd+0x10c/0x270 [<8024028c>] scsi_request_fn+0x28c/0x53c Signed-off-by: Yoichi Yuasa <yoichi_yuasa@xxxxxxxxxxxxxx> diff -pruN -X /home/yuasa/Memo/dontdiff linux-orig/arch/mips/mm/c-r4k.c linux/arch/mips/mm/c-r4k.c --- linux-orig/arch/mips/mm/c-r4k.c 2009-01-15 10:27:30.170434561 +0900 +++ linux/arch/mips/mm/c-r4k.c 2009-01-15 17:06:07.326434524 +0900 @@ -612,6 +612,8 @@ static void r4k_dma_cache_wback_inv(unsi static void r4k_dma_cache_inv(unsigned long addr, unsigned long size) { + unsigned long lsize = cpu_dcache_line_size(); + /* Catch bad driver code */ BUG_ON(size == 0); @@ -620,7 +622,8 @@ static void r4k_dma_cache_inv(unsigned l r4k_blast_scache(); else { cache_op(Hit_Writeback_Inv_SD, addr); - cache_op(Hit_Writeback_Inv_SD, addr + size - 1); + cache_op(Hit_Writeback_Inv_SD, + (addr + size - 1) & ~(lsize - 1)); blast_inv_scache_range(addr, addr + size); } return; @@ -631,7 +634,7 @@ static void r4k_dma_cache_inv(unsigned l } else { R4600_HIT_CACHEOP_WAR_IMPL; cache_op(Hit_Writeback_Inv_D, addr); - cache_op(Hit_Writeback_Inv_D, addr + size - 1); + cache_op(Hit_Writeback_Inv_D, (addr + size - 1) & ~(lsize - 1)); blast_inv_dcache_range(addr, addr + size); }