ppc405 core, VIA VT82C686A chipset, linux_2.4.22_pre5, and IDE DMA woes
John F Davis
johndavi at us.ibm.com
Sun Jan 30 05:12:52 EST 2005
Hello
I am trying to get DMA working on a ppc405 core on a custom SOC with IDE
DMA using a VIA VT82C686A southbridge. I apologize for the length of this
note.
Here is my environment, configuration, attempts at fixing the system, what
works, and what doesn't.
o Using linux 2.4.22 pre5 kernel from ppc devel bitkeeper tree. Using
cross compiler gcc version 3.2.3
o On this box non dma IDE works flawlessy with and without 405 data
caching.
o DMA IDE works when caching is disabled. When caching is enabled and
DMA ide is enabled, the system works for a while and then it gets a Data
Storage Exception when it tries to do a write. The exception is usually
involves writing to a very similar address no matter how and when the
exception occurs.
o I am using hdparm to enable and disable the IDE DMA at the command
line. I ususally cause the oops by running consecutive hdparm tests from
two different TTY logins. If that does not cause it to oops then starting
X windows, playing a movie from disk and then issuing the hdparm test most
certainly will.
o Here are some sample oops messages and ksymoops interpetations. (There
is more info after the oops messages.)
# Oops: kernel access of bad area, sig: 11
NIP: A002EC04 XER: 20000000 LR: A002EB84 SP: ACBC5D60 REGS: acbc5cb0 TRAP:
0800 Tainted: P
MSR: 00001030 EE: 0 PR: 0 FP: 0 ME: 1 IR/DR: 11
DEAR: 5459545D, ESR: 00800000
TASK = acbc4000[156] 'xine' Last syscall: 4
last math 00000000 last altivec 00000000
PLB0: bear= 0x00000000 acr= 0x00000000 besr= 0x00000000
PLB0 to OPB: bear= 0xc27e3183 besr0= 0xc0000000 besr1= 0x00000000
GPR00: 00000000 ACBC5D60 ACBC4000 00000001 00009030 00000001 000009B0
AB126000
GPR08: FFFFFFFF AB14F020 54595459 A02E9DDC 24044082 10115790 00000000
100E10B0
GPR16: ACBC5EA0 AB0FE000 A007ACA8 ACBC5E08 AEB3F080 AEB3F080 000009B0
00001000
GPR24: 00000000 A04D2BA8 00000001 00000000 00001000 000000F0 AB126F60
A02E9DD4
Call backtrace:
00000003 A002E3E4 A003A084 A003A1C0 A003A504 A003AC90 A003B4D8
A007B000 A002A874 A002AECC A0037564 A000279C 0FECCD18 0EFC53BC
0FF50A48 0FEC7914 0FC0B408
produces:*************************
>>NIP; a002ec04 <kmem_find_general_cachep+6ec/2614> <=====
>>GPR1; acbc5d60 <_end+c925038/12618420>
>>GPR2; acbc4000 <_end+c9232d8/12618420>
>>GPR7; ab126000 <_end+ae852d8/12618420>
>>GPR9; ab14f020 <_end+aeae2f8/12618420>
>>GPR11; a02e9ddc <_end+490b4/12618420>
>>GPR16; acbc5ea0 <_end+c925178/12618420>
>>GPR17; ab0fe000 <_end+ae5d2d8/12618420>
>>GPR18; a007aca8 <journal_blocks_per_page+4340/87fc>
>>GPR19; acbc5e08 <_end+c9250e0/12618420>
>>GPR20; aeb3f080 <_end+e89e358/12618420>
>>GPR21; aeb3f080 <_end+e89e358/12618420>
>>GPR25; a04d2ba8 <_end+231e80/12618420>
>>GPR30; ab126f60 <_end+ae86238/12618420>
>>GPR31; a02e9dd4 <_end+490ac/12618420>
Trace; 00000003 Before first symbol
Trace; a002e3e4 <kmem_cache_alloc+10/20>
Trace; a003a084 <get_unused_buffer_head+68/c8>
Trace; a003a1c0 <set_bh_page+dc/334>
Trace; a003a504 <create_empty_buffers+24/908>
Trace; a003ac90 <create_empty_buffers+7b0/908>
Trace; a003b4d8 <block_prepare_write+34/a8>
Trace; a007b000 <journal_blocks_per_page+4698/87fc>
Trace; a002a874 <read_cache_page+5f4/aac>
Trace; a002aecc <generic_file_write+1a0/2400>
Trace; a0037564 <default_llseek+490/e10>
Trace; a000279c <set_context+3b4/5e0>
Trace; 0feccd18 Before first symbol
Trace; 0efc53bc Before first symbol
Trace; 0ff50a48 Before first symbol
Trace; 0fec7914 Before first symbol
Trace; 0fc0b408 Before first symbol
5 warnings and 2 errors issued. Results may not be reliable.
===========================================================
>>NIP; a002ec40 <kmem_find_general_cachep+728/2614> <=====
>>GPR1; ab53dd10 <_end+b29cfe8/125fe420>
>>GPR2; ab53c000 <_end+b29b2d8/125fe420>
>>GPR7; ad4f0000 <_end+d24f2d8/125fe420>
>>GPR8; a0270000 <ide_register_driver+9e3c/be50>
>>GPR9; a02e9ddc <_end+490b4/125fe420>
>>GPR11; a02e9de4 <_end+490bc/125fe420>
>>GPR18; a00284d0 <do_generic_file_read+73c/804>
>>GPR19; ada5ff60 <_end+d7bf238/125fe420>
>>GPR20; ab53ded8 <_end+b29d1b0/125fe420>
>>GPR21; a003ea04 <sb_min_blocksize+60/4c8>
>>GPR25; a052bd04 <_end+28afdc/125fe420>
>>GPR30; a02e9ddc <_end+490b4/125fe420>
>>GPR31; a02e9dd4 <_end+490ac/125fe420>
Trace; 00000000 Before first symbol
Trace; a002e3e4 <kmem_cache_alloc+10/20>
Trace; a003a084 <get_unused_buffer_head+68/c8>
Trace; a003a1c0 <set_bh_page+dc/334>
Trace; a003a504 <create_empty_buffers+24/908>
Trace; a003b094 <block_read_full_page+2ac/2d8>
Trace; a003ead0 <sb_min_blocksize+12c/4c8>
Trace; a00272b4 <filemap_fdatawait+414/4dc>
Trace; a0027c40 <grab_cache_page_nowait+22c/380>
Trace; a0028108 <do_generic_file_read+374/804>
Trace; a0028640 <generic_file_read+a8/9d4>
Trace; a0037414 <default_llseek+340/e10>
Trace; a000279c <set_context+3b8/5e4>
Trace; 00000000 Before first symbol
Trace; 10001dcc Before first symbol
Trace; 10002ba4 Before first symbol
Trace; 10003f94 Before first symbol
Trace; 0fee4920 Before first symbol
Trace; 00000000 Before first symbol
=======================================================
Trace; a00190dc <__tasklet_hi_schedule+204/250>
Trace; a002e3e4 <kmem_cache_alloc+10/20>
Trace; a003a084 <get_unused_buffer_head+68/c8>
Trace; a003a1c0 <set_bh_page+dc/334>
Trace; a003a504 <create_empty_buffers+24/908>
Trace; a003b094 <block_read_full_page+2ac/2d8>
Trace; a003ead0 <sb_min_blocksize+12c/4c8>
Trace; a00272b4 <filemap_fdatawait+414/4dc>
Trace; a0027c40 <grab_cache_page_nowait+22c/380>
Trace; a0027f3c <do_generic_file_read+1a8/804>
Trace; a0028640 <generic_file_read+a8/9d4>
Trace; a0037414 <default_llseek+340/e10>
Trace; a000279c <set_context+3b8/5e4>
Trace; 00000000 Before first symbol
Trace; 10001dcc Before first symbol
Trace; 10002ba4 Before first __ide_dma_write
symbol
Trace; 1__ide_dma_write
0003f94 Before first symbol
Trace; 0fee4920 Before first symbol
Trace; 00000000 Before first symbol
i========================================
# Oops: kernel access of bad area, sig: 11
NIP: A002EC40 XER: 20000000 LR: A002EB84 SP: AF40BD10 REGS: af40bc60 TRAP:
0800 Tainted: P
MSR: 00001030 EE: 0 PR: 0 FP: 0 ME: 1 IR/DR: 11
DEAR: 54D954DD, ESR: 00800000
TASK = af40a000[292] 'hdparm' Last syscall: 3
last math 00000000 last altivec 00000000
PLB0: bear= 0x60000000 acr= 0x00000000 besr= 0x00000000
PLB0 to OPB: bear= 0xc27e3183 besr0= 0xc0000000 besr1= 0x00000000
GPR00: 00000000 AF40BD10 AF40A000 00000001 00009030 00000001 0000000A
AC091000
GPR08: A0270000 A02E9DDC 54D954D9 A02E9DE4 84002082 101EDDE4 00000000
00000000
GPR16: 00000000 00000000 A00284D0 ADC0E760 AF40BED8 A003EA04 00000001
00000000
GPR24: 00000C00 A045BBA0 00000001 00000000 00000400 000000F0 A02E9DDC
A02E9DD4
Call backtrace:
A045FED4 A002E3E4 A003A084 A003A1C0 A003A504 A003B094 A003EAD0
A00272B4 A0027C40 A0028108 A0028640 A0037414 A000279C 00000000
10001DCC 10002BA4 10003F94 0FEE4920 00000000
# Oops: kernel access of bad area, sig: 11
NIP: A002EC40 XER: 20000000 LR: A002EB84 SP: AF40BD10 REGS: af40bc60 TRAP:
0800 Tainted: P
MSR: 00001030 EE: 0 PR: 0 FP: 0 ME: 1 IR/DR: 11
DEAR: 54D954DD, ESR: 00800000
TASK = af40a000[292] 'hdparm' Last syscall: 3
last math 00000000 last altivec 00000000
PLB0: bear= 0x60000000 acr= 0x00000000 besr= 0x00000000
PLB0 to OPB: bear= 0xc27e3183 besr0= 0xc0000000 besr1= 0x00000000
GPR00: 00000000 AF40BD10 AF40A000 00000001 00009030 00000001 0000000A
AC091000
GPR08: A0270000 A02E9DDC 54D954D9 A02E9DE4 84002082 101EDDE4 00000000
00000000
GPR16: 00000000 00000000 A00284D0 ADC0E760 AF40BED8 A003EA04 00000001
00000000
GPR24: 00000C00 A045BBA0 00000001 00000000 00000400 000000F0 A02E9DDC
A02E9DD4
Call backtrace:
A045FED4 A002E3E4 A003A084 A003A1C0 A003A504 A003B094 A003EAD0
A00272B4 A0027C40 A0028108 A0028640 A0037414 A000279C 00000000
10001DCC 10002BA4 10003F94 0FEE4920 00000000
>>NIP; a002ec40 <kmem_find_general_cachep+728/2614> <=====
>>GPR1; af40bd10 <_end+f16afe8/125fe420>
>>GPR2; af40a000 <_end+f1692d8/125fe420>
>>GPR7; ac091000 <_end+bdf02d8/125fe420>
>>GPR8; a0270000 <ide_register_driver+9e3c/be50>
>>GPR9; a02e9ddc <_end+490b4/125fe420>
>>GPR11; a02e9de4 <_end+490bc/125fe420>
>>GPR18; a00284d0 <do_generic_file_read+73c/804>
>>GPR19; adc0e760 <_end+d96da38/125fe420>
>>GPR20; af40bed8 <_end+f16b1b0/125fe420>
>>GPR21; a003ea04 <sb_min_blocksize+60/4c8>
>>GPR25; a045bba0 <_end+1bae78/125fe420>
>>GPR30; a02e9ddc <_end+490b4/125fe420>
>>GPR31; a02e9dd4 <_end+490ac/125fe420>
Trace; a045fed4 <_end+1bf1ac/125fe420>
Trace; a002e3e4 <kmem_cache_alloc+10/20>
Trace; a003a084 <get_unused_buffer_head+68/c8>
Trace; a003a1c0 <set_bh_page+dc/334>
Trace; a003a504 <create_empty_buffers+24/908>
Trace; a003b094 <block_read_full_page+2ac/2d8>
Trace; a003ead0 <sb_min_blocksize+12c/4c8>
Trace; a00272b4 <filemap_fdatawait+414/4dc>
Trace; a0027c40 <grab_cache_page_nowait+22c/380>
Trace; a0028108 <do_generic_file_read+374/804>
Trace; a0028640 <generic_file_read+a8/9d4>
Trace; a0037414 <default_llseek+340/e10>
Trace; a000279c <set_context+3b8/5e4>
Trace; 00000000 Before first symbol
Trace; 10001dcc Before first symbol
Trace; 10002ba4 Before first symbol
Trace; 10003f94 Before first symbol
Trace; 0fee4920 Before first symbol
Trace; 00000000 Before first symbol
==========================================================
added the debug code to drivers/block/ll_rw_blk.c
#Oops: kernel access of bad area, sig: 11
NIP: A002EC04 XER: 20000000 LR: A002EB84 SP: ACF25D60 REGS: acf25cb0 TRAP:
0800 Tainted: P
MSR: 00001030 EE: 0 PR: 0 FP: 0 ME: 1 IR/DR: 11
DEAR: 54D954DD, ESR: 00800000
TASK = acf24000[139] 'xine' Last syscall: 4
last math 00000000 last altivec 00000000
PLB0: bear= 0x60000000 acr= 0x00000000 besr= 0x00000000
PLB0 to OPB: bear= 0xc27e3183 besr0= 0xc0000000 besr1= 0x00000000
GPR00: 00000000 ACF25D60 ACF24000 00000001 00009030 00000001 0000042C
AB9F1000
GPR08: FFFFFFFF ABA1A020 54D954D9 A02E9DDC 24044082 10115790 00000000
100E10B0
GPR16: ACF25EA0 AB9CE000 A007ACA8 ACF25E08 AC58F680 AC58F680 0000042C
00001000
GPR24: 00000000 A04EAF68 00000001 00000000 00001000 000000F0 AB9F1F60
A02E9DD4
Call backtrace:
00000003 A002E3E4 A003A084 A003A1C0 A003A504 A003AC90 A003B4D8
A007B000 A002A874 A002AECC A0037564 A000279C 0FECCD18 0EFC53BC
0FF50A48 0FEC7914 0FC0B408
Was so hosed I could not run ksymoops.
================================
Timing buffered disk reads: Oops: kernel access of bad area, sig: 11
NIP: A002EC28 XER: 20000000 LR: A002EB84 SP: AE1F7D10 REGS: ae1f7c60 TRAP:
0800 Tainted: P
MSR: 00001030 EE: 0 PR: 0 FP: 0 ME: 1 IR/DR: 11
DEAR: 54D954D9, ESR: 00000000
TASK = ae1f6000[131] 'hdparm' Last syscall: 3
last math 00000000 last altivec 00000000
PLB0: bear= 0x60000000 acr= 0x00000000 besr= 0x00000000
PLB0 to OPB: bear= 0xc27e3183 besr0= 0xc0000000 besr1= 0x00000000
GPR00: A02E9DE4 AE1F7D10 AE1F6000 00000001 00009030 00000002 00000003
54D954D9
GPR08: A0270000 00000000 A0270000 00000001 84002042 10025468 00000000
00000000
GPR16: 00000000 00000000 A00284D0 AC3CE760 AE1F7ED8 A003EA1C 00000000
00000000
GPR24: 00000C00 A054755C 00000001 00000000 00000400 000000F0 A02E9DDC
A02E9DD4
Call backtrace:
A00190DC A002E3E4 A003A09C A003A1D8 A003A51C A003B0AC A003EAE8
A00272B4 A0027C40 A0027F3C A0028640 A0037414 A000279C 00000000
10001DCC 10002BA4 10003F94 0FEE4920 00000000
Segmentation fault
Warning (Oops_read): Code line not seen, dumping what data is available
>>NIP; a002ec28 <kmem_find_general_cachep+710/2614> <=====
>>GPR0; a02e9de4 <_end+490bc/125fe420>
>>GPR1; ae1f7d10 <_end+df56fe8/125fe420>
>>GPR2; ae1f6000 <_end+df552d8/125fe420>
>>GPR8; a0270000 <ide_register_driver+9e3c/be50>
>>GPR10; a0270000 <ide_register_driver+9e3c/be50>
>>GPR18; a00284d0 <do_generic_file_read+73c/804>
>>GPR19; ac3ce760 <_end+c12da38/125fe420>
>>GPR20; ae1f7ed8 <_end+df571b0/125fe420>
>>GPR21; a003ea1c <sb_min_blocksize+60/4c8>
>>GPR25; a054755c <_end+2a6834/125fe420>
>>GPR30; a02e9ddc <_end+490b4/125fe420>
>>GPR31; a02e9dd4 <_end+490ac/125fe420>
Trace; a00190dc <__tasklet_hi_schedule+204/250>
Trace; a002e3e4 <kmem_cache_alloc+10/20>
Trace; a003a09c <get_unused_buffer_head+80/e0>
Trace; a003a1d8 <set_bh_page+dc/334>
Trace; a003a51c <create_empty_buffers+24/908>
Trace; a003b0ac <block_read_full_page+2ac/2d8>
Trace; a003eae8 <sb_min_blocksize+12c/4c8>
Trace; a00272b4 <filemap_fdatawait+414/4dc>
Trace; a0027c40 <grab_cache_page_nowait+22c/380>
Trace; a0027f3c <do_generic_file_read+1a8/804>
Trace; a0028640 <generic_file_read+a8/9d4>
Trace; a0037414 <default_llseek+340/e10>
Trace; a000279c <set_context+3b8/5e4>
Trace; 00000000 Before first symbol
Trace; 10001dcc Before first symbol
Trace; 10002ba4 Before first symbol
Trace; 10003f94 Before first symbol
Trace; 0fee4920 Before first symbol
Here is a dump of the configuration space for the isa bridge and ide
interface on the VIA chipset in both human readable form and raw form.
The ISA bridge:
0000:00:01.0 ISA bridge: VIA Technologies, Inc. VT82C686 [Apollo Super
South] (rev 40)
Control: I/O+ Mem+ BusMaster+ SpecCycle- MemWINV- VGASnoop-
ParErr- Stepping+ SERR- FastB2B-
Status: Cap+ 66MHz- UDF- FastB2B- ParErr- DEVSEL=medium >TAbort-
<TAbort- <MAbort- >SERR- <PERR-
Latency: 0
Interrupt: pin ? routed to IRQ 46
Capabilities: [c0] Power Management version 2
Flags: PMEClk- DSI- D1- D2- AuxCurrent=0mA
PME(D0-,D1-,D2-,D3hot-,D3cold-)
Status: D0 PME-Enable- DSel=0 DScale=0 PME-
and in raw form
0000:00:01.0 ISA bridge: VIA Technologies, Inc. VT82C686 [Apollo Super
South] (rev 40)
00: 06 11 86 06 87 00 10 02 40 00 01 06 00 00 80 00
10: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
20: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
30: 00 00 00 00 c0 00 00 00 00 00 00 00 00 00 00 00
40: 08 01 00 00 00 00 00 00 05 01 84 00 00 00 00 03
50: 0e 00 34 00 0f 90 ba 00 00 04 bf 00 00 00 00 00
60: d8 ff 00 00 00 00 00 00 00 00 00 00 00 00 00 00
70: 00 00 00 00 00 00 00 88 00 00 00 00 00 00 00 00
80: 00 00 00 00 00 01 00 00 00 60 00 00 00 00 00 00
90: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
a0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
b0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
c0: 01 00 02 00 00 00 00 00 00 00 00 00 00 00 00 00
d0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
e0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
f0: 00 00 00 00 00 00 42 00 00 00 00 00 00 00 00 00
The IDE Interface:
0000:00:01.1 IDE interface: VIA Technologies, Inc.
VT82C586A/B/VT82C686/A/B/VT823x/A/C PIPC Bus Master IDE (rev 06) (prog-if
8f [Master SecP SecO PriP PriO])
Control: I/O+ Mem+ BusMaster+ SpecCycle- MemWINV- VGASnoop-
ParErr- Stepping- SERR- FastB2B-
Status: Cap+ 66MHz- UDF- FastB2B+ ParErr- DEVSEL=medium >TAbort-
<TAbort- <MAbort- >SERR- <PERR-
Latency: 128
Interrupt: pin ? routed to IRQ 46
Region 0: I/O ports at fff8 [size=8]
Region 1: I/O ports at fff4 [size=4]
Region 2: I/O ports at ffe8 [size=8]
Region 3: I/O ports at ffe4 [size=4]
Region 4: I/O ports at ffd0 [size=16]
Capabilities: [c0] Power Management version 2
Flags: PMEClk- DSI- D1- D2- AuxCurrent=0mA
PME(D0-,D1-,D2-,D3hot-,D3cold-)
Status: D0 PME-Enable- DSel=0 DScale=0 PME-
and in raw form
0000:00:01.1 IDE interface: VIA Technologies, Inc.
VT82C586A/B/VT82C686/A/B/VT823x/A/C PIPC Bus Master IDE (rev 06)
00: 06 11 71 05 07 00 90 02 06 8f 01 01 00 80 00 00
10: f9 ff 00 00 f5 ff 00 00 e9 ff 00 00 e5 ff 00 00
20: d1 ff 00 00 00 00 00 00 00 00 00 00 00 00 00 00
30: 00 00 00 00 c0 00 00 00 00 00 00 00 0e 00 00 00
40: 0b 02 c9 3a 08 00 c0 00 a8 a8 a8 20 3f 00 ff 20
50: 07 07 07 e4 04 00 00 00 a8 a8 a8 a8 00 00 00 00
60: 00 02 00 00 00 00 00 00 00 02 00 00 00 00 00 00
70: 02 01 00 00 00 00 00 00 02 01 00 00 00 00 00 00
80: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
90: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
a0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
b0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
c0: 01 00 02 00 00 00 00 00 00 00 00 00 00 00 00 00
d0: 06 00 71 05 00 00 00 00 00 00 00 00 00 00 00 00
e0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
f0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
Here is a summary of what I have tried in the kernel code.
o I tried the unaligned buffer patch to see if I had alignment problems.
I dont.
o I tried to flush the cache instead of invalidating it in the
consistent_sync PCI_DMA_FROMDEVICE case.
o I tried to flush the consistent sync the memory in the ide_build_sglist
routine in a manner similar to Dan Malek in his 4xx OCP IDE driver.
o I tried to flush the cache based upon the dma table after the
ide_build_dmatable call as done in the Amiga One port which also uses the
VIA chipset.
o I tried converting the kmalloc calls for the sg_table to non cacheable
as well.
Here is the cleaned up diff with the debug printk's and my comments
removed.
diff -Naur orig/arch/ppc/mm/cachemap.c mod/arch/ppc/mm/cachemap.c
--- orig/arch/ppc/mm/cachemap.c 2005-01-29 13:06:41.000000000 -0500
+++ mod/arch/ppc/mm/cachemap.c 2005-01-29 13:04:10.000000000 -0500
@@ -146,10 +146,28 @@
unsigned long start = (unsigned long)vaddr;
unsigned long end = start + size;
switch (direction) {
case PCI_DMA_NONE:
BUG();
case PCI_DMA_FROMDEVICE: /* invalidate only */
+// printk("consistent sync: PCI_DMA_FROMDEVICE\n");
+
+#ifdef CONFIG_DEBUG_CONSISTENT_SYNC
+ if (unlikely(start & (L1_CACHE_LINE_SIZE - 1)) ||
+ unlikely(end & (L1_CACHE_LINE_SIZE - 1)))
+ {
+ static unsigned int count = 0;
+ if (++count < 10)
+ //printk(KERN_WARNING
+ printk(
+ "consistent_sync: 0x%08lx-0x%08lx "
+ "is not properly aligned, lr 0x%p\n",
+ start, end, __builtin_return_address(0));
+ }
+#endif
+
flush_dcache_range(start, end);
+// invalidate_dcache_range(start, end);
break;
case PCI_DMA_TODEVICE: /* writeback only */
+// printk("consistent sync: PCI_DMA_TODEVICE\n");
clean_dcache_range(start, end);
break;
case PCI_DMA_BIDIRECTIONAL: /* writeback and invalidate */
+// printk("consistent sync: PCI_DMA_BIDIRECTIONAL\n");
flush_dcache_range(start, end);
break;
}
diff -Naur orig/drivers/ide/ide-dma.c mod/drivers/ide/ide-dma.c
--- orig/drivers/ide/ide-dma.c 2005-01-29 13:06:53.000000000 -0500
+++ mod/drivers/ide/ide-dma.c 2005-01-29 12:55:15.000000000 -0500
static int ide_build_sglist (ide_hwif_t *hwif, struct request *rq, int
ddir)
{
struct buffer_head *bh;
unsigned long lastdataend = ~0UL;
int nents = 0;
if (hwif->sg_dma_active)
BUG();
@@ -270,6 +291,17 @@
}
if (contig) {
+ unsigned int size, addr;
+
+ addr = virt_to_bus(bh->b_data);
+ size = bh->b_size;
+ if (ddir)
+ consistent_sync(bh->b_data, size,
PCI_DMA_TODEVICE);
+ else
+ consistent_sync(bh->b_data, size,
PCI_DMA_FROMDEVICE);
+
+
+
sg[nents - 1].length += bh->b_size;
lastdataend += bh->b_size;
continue;
@@ -281,10 +313,26 @@
memset(&sg[nents], 0, sizeof(*sg));
if (bh->b_page) {
+ unsigned int size, addr;
+
+
+ addr = virt_to_bus(bh->b_data);
+ size = bh->b_size;
+ if (ddir)
+ consistent_sync(bh->b_data, size,
PCI_DMA_TODEVICE);
+ else
+ consistent_sync(bh->b_data, size,
PCI_DMA_FROMDEVICE);
+
+
sg[nents].page = bh->b_page;
sg[nents].offset = bh_offset(bh);
lastdataend = bh_phys(bh) + bh->b_size;
+ //printk("we are using pages\n");
+
+
+
} else {
+ printk("we are using datas\n");
if ((unsigned long) bh->b_data < PAGE_SIZE)
BUG();
@@ -300,6 +348,8 @@
BUG();
hwif->sg_dma_direction = ddir;
return pci_map_sg(hwif->pci_dev, sg, nents, ddir);
}
@@ -686,9 +751,18 @@
u8 dma_stat = 0, lba48 = (drive->addressing == 1) ? 1 : 0;
task_ioreg_t command = WIN_NOP;
if (!(count = ide_build_dmatable(drive, rq, PCI_DMA_FROMDEVICE)))
/* try PIO instead of DMA */
return 1;
+#if 1 /* MAI: make sure RAM's copy of dma table is up to date */
+ /* flush (start, stop) */
+// printk("ide_dma_read\n");
+// printk("\tflush_dcache_range start=%x
size=%x\n",hwif->dmatable_cpu, hwif->dmatable_cpu +(count << 3));
+ flush_dcache_range (hwif->dmatable_cpu, hwif->dmatable_cpu +
(count << 3));
+#endif
/* PRD table */
hwif->OUTL(hwif->dmatable_dma, hwif->dma_prdtable);
/* specify r/w */
@@ -732,9 +806,18 @@
u8 dma_stat = 0, lba48 = (drive->addressing == 1) ? 1 : 0;
task_ioreg_t command = WIN_NOP;
+// printk("__ide_dma_write\n");
+
+
if (!(count = ide_build_dmatable(drive, rq, PCI_DMA_TODEVICE)))
/* try PIO instead of DMA */
return 1;
+#if 1 /* MAI: make sure RAM's copy of dma table is up to date */
+ // This is flushing the virt address table.
+// printk("ide_dma_write\n");
+// printk("\tflush_dcache_range start=%x
size=%x\n",hwif->dmatable_cpu, hwif->dmatable_cpu +(count << 3));
+ flush_dcache_range (hwif->dmatable_cpu, hwif->dmatable_cpu +
(count << 3));
+#endif
/* PRD table */
hwif->OUTL(hwif->dmatable_dma, hwif->dma_prdtable);
/* specify r/w */
@@ -994,12 +1077,14 @@
hwif->dmatable_cpu = NULL;
}
if (hwif->sg_table) {
- kfree(hwif->sg_table);
+/* jfd kfree(hwif->sg_table); */
+ pci_free_consistent(NULL, sizeof(struct scatterlist) *
PRD_ENTRIES, hwif->sg_table,NULL);
hwif->sg_table = NULL;
}
return 1;
}
+
int ide_release_mmio_dma (ide_hwif_t *hwif)
{
if ((hwif->dma_extra) && (hwif->channel == 0))
@@ -1039,11 +1124,26 @@
int ide_allocate_dma_engine (ide_hwif_t *hwif)
{
+
+ printk("ide_allocate_dma_engine\n");
+
hwif->dmatable_cpu = pci_alloc_consistent(hwif->pci_dev,
PRD_ENTRIES * PRD_BYTES,
&hwif->dmatable_dma);
+
+ printk("\t dma table bus addr %x\n",hwif->dmatable_dma);
+ printk("\t dma table virt addr %x\n",hwif->dmatable_cpu);
+ printk("\t size
%x*%x=%x\n",PRD_ENTRIES,PRD_BYTES,PRD_ENTRIES*PRD_BYTES);
+
+
+
+ hwif->sg_table = pci_alloc_consistent(NULL,sizeof(struct
scatterlist) * PRD_ENTRIES,
+ &hwif->sg_table);
+#if 0
hwif->sg_table = kmalloc(sizeof(struct scatterlist) * PRD_ENTRIES,
GFP_KERNEL);
+jfd
+#endif
More information about the Linuxppc-embedded
mailing list