----- 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