Skip site navigation (1)Skip section navigation (2)
Date:      Tue, 2 Sep 2003 00:56:46 +0900
From:      Hiroyuki Aizu <eyes@navi.org>
To:        freebsd-current@freebsd.org
Subject:   Re: ATAng suspend/resume support broken
Message-ID:  <20030902005646.7f9cc963.eyes@navi.org>
In-Reply-To: <20030828215209.T41901@root.org>
References:  <20030828215209.T41901@root.org>

next in thread | previous in thread | raw e-mail | index | archive | help

[-- Attachment #1 --]
Hi.

On Thu, 28 Aug 2003 21:57:24 -0700 (PDT)
Nate Lawson <nate@root.org> wrote:

> With today's ATAng, I can suspend my laptop but when I resume, the system
> hangs.  I'll try to get the exact dmesg with a serial console since
> syscons gets screwed up by resuming (this is normal behavior).  In any
> case, my laptop hangs with the drive light on while trying to reset the
> ata controller.  I can't enter DDB.  By reverting just the ATAng commit to
> 2003/08/23, suspend and resume work well.  Here is my dmesg from a working
> suspend/resume...
> 
> -Nate

My laptop has same behavior. So I compare ATAng with ATAold and solve this
problem. I found re-init routine must necessary at wakeup. 
I made patches and attach to this mail.

These three are patches for re-init. At least, this works for my machine.
ata-all.c.diff
ata-all.h.diff
ata-disk.c.diff

And I make one more patch "ata-lowlevel.c.diff".
The Reason is ATAng code fonund ghost device on slave at resume time like this.

ad1: 8994829560181951MB <\M^?\M-%\M^?\M-%\M^?\M-%\M^?\M-%\M^?\M-%\M^?\M-%\M^?\M-
%\M^?\M-%\M^?\M-%\M^?\M-%\M^?\M-%\M^?\M-%\M^?\M-%\M^?\M-%\M^?\M-%\M^?\M-%\M^?\M-
%\M^?\M-%\M^?\M-%\M^?\M-%> [676635847171814/165/165] at ata0-slave UDMA66

Mysteriously, ATAold and ATAng code using variable "ostat[01]" that save status 
before reset channel. I'm not familier with ATA, so maybe I'm 
misunderstanding.

Please consider these patches.

At last, I can sleep (-.-)
--
Hiroyuki Aizu

[-- Attachment #2 --]
--- ata-all.c.orig	Mon Sep  1 22:22:19 2003
+++ ata-all.c	Tue Sep  2 00:16:29 2003
@@ -257,6 +257,13 @@
 	if ((newdev & (ATA_ATA_SLAVE | ATA_ATAPI_SLAVE)) &&
 	    ch->device[SLAVE].attach)
 	    ch->device[SLAVE].attach(&ch->device[SLAVE]);
+    } else {
+	if ((ch->devices & (ATA_ATA_MASTER | ATA_ATAPI_MASTER)) &&
+	    ch->device[MASTER].reinit)
+	    ch->device[MASTER].reinit(&ch->device[MASTER]);
+	if ((ch->devices & (ATA_ATA_SLAVE | ATA_ATAPI_SLAVE)) &&
+	    ch->device[SLAVE].reinit)
+	    ch->device[SLAVE].reinit(&ch->device[SLAVE]);
     }
 #ifdef DEV_ATAPICAM
     atapi_cam_reinit_bus(ch);

[-- Attachment #3 --]
--- ata-all.h.orig	Mon Aug 25 20:13:04 2003
+++ ata-all.h	Tue Sep  2 00:15:14 2003
@@ -218,6 +218,7 @@
     void			*softc;		/* ptr to softc for device */
     void			(*attach)(struct ata_device *atadev);
     void			(*detach)(struct ata_device *atadev);
+    void			(*reinit)(struct ata_device *atadev);
     void			(*start)(struct ata_device *atadev);
     int				flags;
 #define		ATA_D_USE_CHS		0x0001

[-- Attachment #4 --]
--- ata-disk.c.orig	Mon Aug 25 18:01:49 2003
+++ ata-disk.c	Tue Sep  2 00:15:31 2003
@@ -55,6 +55,7 @@
 
 /* prototypes */
 static void ad_detach(struct ata_device *);
+static void ad_reinit(struct ata_device *);
 static void ad_start(struct ata_device *);
 static void ad_done(struct ata_request *);
 static disk_open_t adopen;
@@ -152,6 +153,7 @@
 
     /* setup the function ptrs */
     atadev->detach = ad_detach;
+    atadev->reinit = ad_reinit;
     atadev->start = ad_start;
     atadev->softc = adp;
 
@@ -202,6 +204,19 @@
     atadev->softc = NULL;
     atadev->flags = 0;
     free(adp, M_AD);
+}
+
+static void
+ad_reinit(struct ata_device *atadev)
+{
+    struct ad_softc *adp = atadev->softc;
+
+    ata_controlcmd(atadev, ATA_SET_MULTI, 0, 0, (adp->max_iosize / DEV_BSIZE));
+
+    if (ata_dma && atadev->channel->dma)
+        atadev->setmode(atadev, ATA_DMA_MAX);
+    else
+        atadev->setmode(atadev, ATA_PIO_MAX);
 }
 
 static int

[-- Attachment #5 --]
--- ata-lowlevel.c.orig	Mon Sep  1 20:13:21 2003
+++ ata-lowlevel.c	Tue Sep  2 00:15:20 2003
@@ -591,7 +591,7 @@
     if (!mask)
 	return;
 
-    if (mask & 0x01 && ostat0 != 0x00 &&
+    if (mask & 0x01 && stat0 != 0x00 &&
         !(ch->devices & (ATA_ATA_MASTER | ATA_ATAPI_MASTER))) {
 	ATA_IDX_OUTB(ch, ATA_DRIVE, ATA_D_IBM | ATA_MASTER);
 	DELAY(10);
@@ -604,7 +604,7 @@
 	if (err != 0x58 && lsb == 0xa5)
 	    ch->devices |= ATA_ATA_MASTER;
     }
-    if (mask & 0x02 && ostat1 != 0x00 &&
+    if (mask & 0x02 && stat1 != 0x00 &&
 	!(ch->devices & (ATA_ATA_SLAVE | ATA_ATAPI_SLAVE))) {
 	ATA_IDX_OUTB(ch, ATA_DRIVE, ATA_D_IBM | ATA_SLAVE);
 	DELAY(10);

Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?20030902005646.7f9cc963.eyes>