Subject: Re: 1.3 apm problems
To: Johan Danielsson <joda@pdc.kth.se>
From: Manuel Bouyer <bouyer@antioche.lip6.fr>
List: port-i386
Date: 05/06/1998 10:34:28
On May 6, Johan Danielsson wrote
> 
> After a resume there seems to be a short period (~26-27 seconds)
> during which the IDE controller (or disk or whatever) doesn't seem
> very responsive. 

I suspect this is the time needed by the IDE disk to recover from
the 'sleep' mode.

> Specifically files read during that period are
> mostly garbage, for instance /etc/apm/resume. If I put a `sleep(30)'
> in apmd.c:resume(), those specific problems goes away, but this sounds
> like a more serious problem.
> 

There is a problem in 1.3 and 1.3.1 with disk adress calculation. Basically,
when retrying a command after a timeout, the wrong disk adress is used
(reported by Robert V. Baron).
This is what happens at resume time: the disk time out, the command is
retried and data are read from the wrong disk block. This has been fixed
in -current, and will be fixed in 1.3.2. A patch against 1.3.1 is appended
at the end.

--
Manuel Bouyer, LIP6, Universite Paris VI.           Manuel.Bouyer@lip6.fr
--

Index: wd.c
===================================================================
RCS file: /archive/cvs/cvsroot/NetBSD/src/sys/dev/isa/wd.c,v
retrieving revision 1.1.1.1
diff -u -r1.1.1.1 wd.c
--- wd.c	1997/12/15 16:49:50	1.1.1.1
+++ wd.c	1998/04/23 11:55:27
@@ -285,7 +285,7 @@
 	struct buf *dp, *bp=0;
 	struct wd_link *d_link = wd->d_link;
 	struct wdc_xfer *xfer;
-	u_long p_offset; 
+	daddr_t blkno, p_offset;
 
 	while (d_link->openings > 0) {
 
@@ -304,6 +304,8 @@
 		  wd->sc_dk.dk_label->d_partitions[WDPART(bp->b_dev)].p_offset;
 		else
 			p_offset = 0;
+		blkno = bp->b_blkno + p_offset;
+		blkno /= (wd->d_link->sc_lp->d_secsize / DEV_BSIZE);
 
 		xfer = wdc_get_xfer(0);
 		if (xfer == NULL)
@@ -311,11 +313,10 @@
 
 		xfer->d_link = d_link;
 		xfer->c_bp = bp;
-		xfer->c_p_offset = p_offset;
 		xfer->databuf = bp->b_data;
 		xfer->c_bcount = bp->b_bcount;
 		xfer->c_flags |= bp->b_flags & (B_READ|B_WRITE);
-		xfer->c_blkno = bp->b_blkno;
+		xfer->c_blkno = blkno;
 
 		/* Instrumentation. */
 		disk_busy(&wd->sc_dk);
Index: wdc.c
===================================================================
RCS file: /archive/cvs/cvsroot/NetBSD/src/sys/dev/isa/wdc.c,v
retrieving revision 1.1.1.2
diff -u -r1.1.1.2 wdc.c
--- wdc.c	1998/01/26 13:45:40	1.1.1.2
+++ wdc.c	1998/04/23 11:55:31
@@ -438,15 +438,10 @@
 
 	/* When starting a transfer... */
 	if (xfer->c_skip == 0) {
-		daddr_t blkno;
-
 		WDDEBUG_PRINT(("\n%s: wdc_ata_start %s %d@%d; map ",
 		    wdc->sc_dev.dv_xname,
 		    (xfer->c_flags & B_READ) ? "read" : "write",
 		    xfer->c_bcount, xfer->c_blkno));
-
-		blkno = xfer->c_blkno+xfer->c_p_offset;
-		xfer->c_blkno = blkno / (d_link->sc_lp->d_secsize / DEV_BSIZE);
 	} else {
 		WDDEBUG_PRINT((" %d)%x", xfer->c_skip,
 		    inb(wdc->sc_iobase + wd_altsts)));
Index: wdlink.h
===================================================================
RCS file: /archive/cvs/cvsroot/NetBSD/src/sys/dev/isa/wdlink.h,v
retrieving revision 1.1.1.1
diff -u -r1.1.1.1 wdlink.h
--- wdlink.h	1997/12/15 16:49:51	1.1.1.1
+++ wdlink.h	1998/04/23 11:55:32
@@ -122,7 +122,6 @@
 	int c_skip;		/* bytes already transferred */
 	int c_nblks;		/* number of blocks currently transferring */
 	int c_nbytes;		/* number of bytes currently transferring */
-	u_long c_p_offset;	/* offset of the partition */
 	TAILQ_ENTRY(wdc_xfer) c_xferchain;
 	LIST_ENTRY(wdc_xfer) free_list;
 };