Fw: IDE DMA on ppc405 with via VT82C686
John F Davis
johndavi at us.ibm.com
Mon Feb 7 11:54:35 EST 2005
----- Forwarded by John F Davis/Raleigh/IBM on 02/06/2005 07:54 PM -----
John F Davis/Raleigh/IBM
02/06/2005 03:41 PM
To
linuxppc-embedded-bounces at ozlabs.org
cc
andre at linux-ide.org, vojtech at suse.cz, maratbn at yahoo.com,
jean-luc.coulon at fnac.net
Subject
IDE DMA on ppc405 with via VT82C686
Hello
I am still trying to get this IDE DMA code working. I have modified
(hacked) the ide_build_dmatable so that it flushes the buffer for each
range of
memory that is modified by the dma bus master. I am certain I have
flushed
the cache properly as shown below, but the problem persists.
Below are two traces. The first one is from my
log buffer utility which shows the operation of the modified
ide_build_dmatable routine.
The second one is from the logic analyzer and it corresponds to the first
dma operation.
Lastly, I have the entire ide_build_dmatable routine for reference as
well as the resulting ksymoops. Note, this code appears to be rock solid
for running multiple consecutive hdparm tests. ie. enable dma and then
issue "while true; do hdparm -t /dev/hda; done" in four logins to the
target
with ssh.
However, I get the oops when I start playback of a video in Xine from
the disk.
I am at the point now, where my next task is to try this board with a
different
IDE controller and see if its a problem with the IDE DMA code for this
non cache coherent processor or if its a problem in the VIA driver.
JD
Truncated portion of my log buffer.
----------------------------------------------------
IBM john f. davis utils
**************************************
ide_build_dmatable
ide_build_sglist
sg_table -> dma/prd table 16
bcount = f000
table (cpu view) = b2009000 (bus view) = fefd000
cpu view addr [b2009000] = 10c00e
cpu view data [b2009004] = 100000
bus view addr [fefd000] = ec01000
bus view data [fefd004] = 1000
flush_dcache_range (aec01000, aec02000)
sg_table -> dma/prd table 15
bcount = 10000
table (cpu view) = b2009008 (bus view) = fefd008
cpu view addr [b2009008] = c00e
cpu view data [b200900c] = 100000
bus view addr [fefd008] = ec00000
bus view data [fefd00c] = 1000
flush_dcache_range (aec00000, aec01000)
sg_table -> dma/prd table 14
bcount = 1000
table (cpu view) = b2009010 (bus view) = fefd010
cpu view addr [b2009010] = f0bf0e
cpu view data [b2009014] = 100000
bus view addr [fefd010] = ebff000
bus view data [fefd014] = 1000
flush_dcache_range (aebff000, aec00000)
...
...
Truncated portion of Logic Analyzer Trace
----------------------------------------------------
Listing(Listing<1>) - 22 May 2003 (23:45)
State Number ADDR FUTUREPLUS SYSTEMS c 1996
Decimal Hex PCI BUS TRANSACTIONS REV 1.2
________________ ___________ ____________________________________
...
...
44 0000FFD4 I/O WRITE ADR=0000FFD4
45 0FEFD000 D32=0FEFD000
46 0FEFD000 IDLE
47 0000FFD4 IDLE
...
...
...
71 0FEFD000 MEM READ ADR=0FEFD000
72 0BF9D000 STOP-NO DATA XFERED-RETRY
73 0FEFD000 MEM READ ADR=0FEFD000
74 0EC01000 D32=0EC01000
75 00001000 D32=00001000
76 00001000 IDLE
77 00001000 IDLE
78 000000A1 I/O WRITE ADR=000000A1
79 3F3F3F3F D32=xxxx3Fxx STOP#
80 3F3F3F3F IDLE
81 000000A1 IDLE
82 00000021 I/O WRITE ADR=00000021
83 F9F9F9F9 D32=xxxxF9xx STOP#
84 F9F9F9F9 IDLE
85 00000021 IDLE
86 0EC01000 MEM WRITE ADR=0EC01000
87 1000B8FA D32=1000B8FA
88 00BCD08E D32=00BCD08E
89 0000B8B0 D32=0000B8B0
90 C08ED88E D32=C08ED88E
91 7C00BEFB D32=7C00BEFB
92 B90600BF D32=B90600BF
Modified ide_build_dma_table routine
----------------------------------------------------
/* JFD NOTES
* This is called second after the dma_read is started.
*/
int ide_build_dmatable (ide_drive_t *drive, struct request *rq, int ddir)
{
ide_hwif_t *hwif = HWIF(drive);
unsigned int *table = hwif->dmatable_cpu; /* JFD Blach table
gets the non cached memory */
volatile unsigned int *tableJFD;
unsigned int is_trm290 = (hwif->chipset == ide_trm290) ? 1 : 0;
unsigned int count = 0;
unsigned int countJFD;
int i,m;
struct scatterlist *sg;
unsigned int *prd_entry;
unsigned int flush_start_addr;
unsigned int flush_length;
// jd_print_it("ide_build_dmatable\n");
if (rq->cmd == IDE_DRIVE_TASKFILE) {
printk("calling ide_raw_build_sglist\n");
hwif->sg_nents = i = ide_raw_build_sglist(hwif, rq);
} else {
/* JFD we call this routine each time */
// printk("calling ide_build_sglist\n");
hwif->sg_nents = i = ide_build_sglist(hwif, rq, ddir);
}
if (!i)
return 0;
sg = hwif->sg_table;
while (i && sg_dma_len(sg)) {
u32 cur_addr;
u32 cur_len;
cur_addr = sg_dma_address(sg); /* jfd blach these are
real addresses */
cur_len = sg_dma_len(sg);
// jd_print_it("sg_table -> dma/PRD table %i\n", i);
/*
* Fill in the dma table, without crossing any 64kB
boundaries.
* Most hardware requires 16-bit alignment of all blocks,
* but the trm290 requires 32-bit alignment.
*/
while (cur_len) {
tableJFD=table;
if (count++ >= PRD_ENTRIES) {
printk("%s: DMA table too small\n",
drive->name);
goto use_pio_instead;
} else {
u32 xcount, bcount = 0x10000 - (cur_addr &
0xffff);
jd_print_it("bcount = %x \n",bcount);
if (bcount > cur_len)
bcount = cur_len;
// JFD writes the address to the PRD table
*table++ = cpu_to_le32(cur_addr);
xcount = bcount & 0xffff;
countJFD=xcount;
if (is_trm290)
xcount = ((xcount >> 2) - 1) <<
16;
if (xcount == 0x0000) {
/*
* Most chipsets correctly interpret a length of 0x0000 as 64KB,
* but at least one (e.g. CS5530) misinterprets it as zero (!).
* So here we break the 64KB entry into two 32KB entries instead.
*/
if (count++ >= PRD_ENTRIES) {
printk("%s: DMA table too
small\n", drive->name);
goto use_pio_instead;
}
// JFD Write the truncated length
to the PRD table
*table++ = cpu_to_le32(0x8000);
// JFD Write the address for the
next truncated length to the PRD table
*table++ = cpu_to_le32(cur_addr +
0x8000);
xcount = 0x8000;
// cut out the logging for real test
#if 0
jd_print_it("table-trunc (cpu
view) = %x (bus view) = %x\n",tableJFD, virt_to_bus(tableJFD));
jd_print_it("\tCPU View ADDR [%x]
= %x\n",tableJFD, *tableJFD);
jd_print_it("\tCPU View DATA [%x]
= %x\n",tableJFD+1, *(tableJFD+1));
jd_print_it("\tBUS View ADDR [%x]
= %x\n",virt_to_bus(tableJFD), le32_to_cpu(*tableJFD));
jd_print_it("\tBUS View DATA [%x]
= %x\n",virt_to_bus(tableJFD+1), le32_to_cpu(*(tableJFD+1)));
#endif
flush_start_addr =
bus_to_virt((unsigned int *)le32_to_cpu(*tableJFD));
flush_length =
le32_to_cpu(*(tableJFD+1));
// jd_print_it("flush_dcache_range
(%x, %x)\n", flush_start_addr, flush_start_addr + flush_length);
flush_dcache_range
(flush_start_addr, flush_start_addr + flush_length );
// have to increment our pointer
to the next PRD address loc as well.
tableJFD++;
tableJFD++;
}
// JFD Write the length (could be trucated
per above) to the PRD table
*table++ = cpu_to_le32(xcount);
cur_addr += bcount;
cur_len -= bcount;
}
// cut out the logging for real test.
#if 0
jd_print_it("table (cpu view) = %x
(bus view) = %x\n",tableJFD, virt_to_bus(tableJFD));
jd_print_it("\tCPU View ADDR [%x]
= %x\n",tableJFD, *tableJFD);
jd_print_it("\tCPU View DATA [%x]
= %x\n",tableJFD+1, *(tableJFD+1));
jd_print_it("\tBUS View ADDR [%x]
= %x\n",virt_to_bus(tableJFD), le32_to_cpu(*tableJFD));
jd_print_it("\tBUS View DATA [%x]
= %x\n",virt_to_bus(tableJFD+1), le32_to_cpu(*(tableJFD+1)));
#endif
flush_start_addr =
bus_to_virt((unsigned int *)le32_to_cpu(*tableJFD));
flush_length =
le32_to_cpu(*(tableJFD+1));
// jd_print_it("flush_dcache_range
(%x, %x)\n", flush_start_addr, flush_start_addr + flush_length);
flush_dcache_range
(flush_start_addr, flush_start_addr + flush_length );
#if 0
// Lets try to read that address into a variable
to see if it "flushes that cache entry"
for (m=0; m< 0x1000;m++) {
ulFoo = *(unsigned int*)
bus_to_virt(le32_to_cpu(*tableJFD++));
}
#endif
}
sg++;
i--;
}
if (count) {
if (!is_trm290)
*--table |= cpu_to_le32(0x80000000);
return count;
}
printk("%s: empty DMA table?\n", drive->name);
use_pio_instead:
pci_unmap_sg(hwif->pci_dev,
hwif->sg_table,
hwif->sg_nents,
hwif->sg_dma_direction);
hwif->sg_dma_active = 0;
return 0; /* revert to PIO for this request */
}
Ksymoops dump
----------------------------------------------------
003AF9C A002F770 A002EC18 A003B14C A003B288 A003B5E8 A003C1E4
AA003AF9C A002F770 A002EC18 A003B14C A003B288 A003B5E8 A003C1E4
007CA8C A0027690 A0028044 A0028518 A0028A5C A003840C A000279C
0A007CA8C A0027690 A0028044 A0028518 A0028A5C A003840C A000279C
FECCB68 0F833B80 0F59D02C 0F59D298 0F59C830 0FF5B278 0FEC7914
00FECCB68 0F833B80 0F59D02C 0F59D298 0F59C830 0FF5B278 0FEC7914
FC0B408
0FC0B408
Warning (Oops_read): Code line not seen, dumping what data is available
>>NIP; a002fc68 <kmem_find_general_cachep+da4/2bb4> <=====
>>GPR1; ac803cf0 <_end+c55ffc8/125f6420>
>>GPR2; ac802000 <_end+c55e2d8/125f6420>
>>GPR3; a02eb1c8 <_end+474a0/125f6420>
>>GPR4; ac0b4000 <_end+be102d8/125f6420>
>>GPR9; ac12c020 <_end+be882f8/125f6420>
>>GPR11; a02eb1d0 <_end+474a8/125f6420>
>>GPR18; a00288ec <do_generic_file_read+74c/814>
>>GPR19; ad3fc834 <_end+d158b0c/125f6420>
>>GPR20; ac803ed8 <_end+c5601b0/125f6420>
>>GPR21; a007c768 <journal_blocks_per_page+4390/8868>
>>GPR25; a04ff860 <_end+25bb38/125f6420>
>>GPR29; a02eb1c8 <_end+474a0/125f6420>
>>GPR30; ac0b4f60 <_end+be11238/125f6420>
>>GPR31; a02eb1c8 <_end+474a0/125f6420>
Trace; a003af9c <bread+10/138>
Trace; a002f770 <kmem_find_general_cachep+8ac/2bb4>
Trace; a002ec18 <kmem_cache_alloc+10/20>
Trace; a003b14c <get_unused_buffer_head+68/c8>
Trace; a003b288 <set_bh_page+dc/350>
Trace; a003b5e8 <create_empty_buffers+24/960>
Trace; a003c1e4 <block_read_full_page+2c0/2ec>
Trace; a007ca8c <journal_blocks_per_page+46b4/8868>
Trace; a0027690 <filemap_fdatawait+424/4ec>
Trace; a0028044 <grab_cache_page_nowait+230/38c>
Trace; a0028518 <do_generic_file_read+378/814>
Trace; a0028a5c <generic_file_read+a8/9e4>
Trace; a003840c <default_llseek+340/e28>
Trace; a000279c <set_context+3b4/5e0>
Trace; 0feccb68 Before first symbol
Trace; 0f833b80 Before first symbol
Trace; 0f59d02c Before first symbol
Trace; 0f59d298 Before first symbol
Trace; 0f59c830 Before first symbol
Trace; 0ff5b278 Before first symbol
Trace; 0fec7914 Before first symbol
Trace; 0fc0b408 Before first symbol
5 warnings and 2 errors issued. Results may not be reliable.
-------------- next part --------------
An HTML attachment was scrubbed...
URL: http://ozlabs.org/pipermail/linuxppc-embedded/attachments/20050206/aa341454/attachment.htm
More information about the Linuxppc-embedded
mailing list