[U-Boot] [PATCH] IDE: Improving speed on reading data Part 1/1

Stefan Althoefer stefan.althoefer at web.de
Thu Dec 4 22:09:24 CET 2008


[PATCH] IDE: Improving speed on reading data

This patch improves the speed when reading blocks from
IDE devices by reading more than one block at a time. Up to
128 blocks are requested in one read command.

On my testplatform (Janz emPC-A400 with CompactFLASH card)
this nearly doubled speed.

Also the ide_wait() code was rewritten to have lower latency
by polling more frequently for status.


The patch is against "latest" u-boot git-repository

Please (still) be patient if style of submission or patches are
offending.

Signed-off-by: Stefan Althoefer <stefan.althoefer at web.de>
----

diff -uprN u-boot-orig//common/cmd_ide.c u-boot/common/cmd_ide.c
--- u-boot-orig//common/cmd_ide.c	2008-12-02 17:25:31.000000000 +0100
+++ u-boot/common/cmd_ide.c	2008-12-03 09:22:29.000000000 +0100
@@ -1302,6 +1361,7 @@ ulong ide_read (int device, lbaint_t blk
 	ulong n = 0;
 	unsigned char c;
 	unsigned char pwrsave=0; /* power save */
+	ulong scnt;
 #ifdef CONFIG_LBA48
 	unsigned char lba48 = 0;
 
@@ -1346,7 +1406,7 @@ ulong ide_read (int device, lbaint_t blk
 	}
 
 
-	while (blkcnt-- > 0) {
+	while (blkcnt > 0) {
 
 		c = ide_wait (device, IDE_TIME_OUT);
 
@@ -1368,7 +1428,8 @@ ulong ide_read (int device, lbaint_t blk
 #endif
 		}
 #endif
-		ide_outb (device, ATA_SECT_CNT, 1);
+		scnt = (blkcnt > 128) ? 128 : blkcnt;
+		ide_outb (device, ATA_SECT_CNT, scnt);
 		ide_outb (device, ATA_LBA_LOW,  (blknr >>  0) & 0xFF);
 		ide_outb (device, ATA_LBA_MID,  (blknr >>  8) & 0xFF);
 		ide_outb (device, ATA_LBA_HIGH, (blknr >> 16) & 0xFF);
@@ -1387,32 +1448,36 @@ ulong ide_read (int device, lbaint_t blk
 			ide_outb (device, ATA_COMMAND,  ATA_CMD_READ);
 		}
 
-		udelay (50);
+		while (scnt > 0) {
+			udelay (50);
 
-		if(pwrsave) {
-			c = ide_wait (device, IDE_SPIN_UP_TIME_OUT);	/* may take up to 4 sec */
-			pwrsave=0;
-		} else {
-			c = ide_wait (device, IDE_TIME_OUT);	/* can't take over 500 ms */
-		}
+			if(pwrsave) {
+				c = ide_wait (device, IDE_SPIN_UP_TIME_OUT);	/* may take up to 4 sec */
+				pwrsave=0;
+			} else {
+				c = ide_wait (device, IDE_TIME_OUT);	/* can't take over 500 ms */
+			}
 
-		if ((c&(ATA_STAT_DRQ|ATA_STAT_BUSY|ATA_STAT_ERR)) != ATA_STAT_DRQ) {
+			if ((c&(ATA_STAT_DRQ|ATA_STAT_BUSY|ATA_STAT_ERR)) != ATA_STAT_DRQ) {
 #if defined(CONFIG_SYS_64BIT_LBA) && defined(CONFIG_SYS_64BIT_VSPRINTF)
-			printf ("Error (no IRQ) dev %d blk %qd: status 0x%02x\n",
-				device, blknr, c);
+				printf ("Error (no IRQ) dev %d blk %qd: status 0x%02x\n",
+					device, blknr, c);
 #else
-			printf ("Error (no IRQ) dev %d blk %ld: status 0x%02x\n",
-				device, (ulong)blknr, c);
+				printf ("Error (no IRQ) dev %d blk %ld: status 0x%02x\n",
+					device, (ulong)blknr, c);
 #endif
-			break;
-		}
+				break;
+			}
 
-		input_data (device, buffer, ATA_SECTORWORDS);
-		(void) ide_inb (device, ATA_STATUS);	/* clear IRQ */
-
-		++n;
-		++blknr;
-		buffer += ATA_BLOCKSIZE;
+			input_data (device, buffer, ATA_SECTORWORDS);
+			(void) ide_inb (device, ATA_STATUS);	/* clear IRQ */
+
+			++n;
+			++blknr;
+			--blkcnt;
+			--scnt;
+			buffer += ATA_BLOCKSIZE;
+		}
 	}
 IDE_READ_E:
 	ide_led (DEVICE_LED(device), 0);	/* LED off	*/
@@ -1548,11 +1613,11 @@ OUT:
  */
 static uchar ide_wait (int dev, ulong t)
 {
-	ulong delay = 10 * t;		/* poll every 100 us */
+	ulong delay = (1000/5) * t;		/* poll every 5 us */
 	uchar c;
 
 	while ((c = ide_inb(dev, ATA_STATUS)) & ATA_STAT_BUSY) {
-		udelay (100);
+		udelay (5);
 		if (delay-- == 0) {
 			break;
 		}


More information about the U-Boot mailing list