Skip site navigation (1)Skip section navigation (2)
Date:      Wed, 16 Mar 2005 11:33:39 +0600
From:      Max Khon <fjoe@samodelkin.net>
To:        freebsd-current@freebsd.org
Cc:        sos@freebsd.org
Subject:   ATAng: reboot after panic, crashdumps [PATCH]
Message-ID:  <20050316053338.GA69911@samodelkin.net>

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

--PEIAKu/WMn1b1Hv9
Content-Type: text/plain; charset=us-ascii
Content-Disposition: inline

Hi!

Attached patch fixes reboot after panic for me on RELENG_5 and RELENG_5_3.
Crashdumps work again for me as well.

The problem was in ata_shutdown() -- ATA_FLUSHCACHE request issued from
ata_shutdown() never completes (ata_queue_request() sleeps in
sema_wait(&request->done)) because ata_interrupt() is never called
(callouts do not work as well, so that if the controller is busy
ATA_FLUSHCACHE was not retried).

I am not sure if "if (panicstr == NULL)" check is required (for normal
shutdown sequence). addump() does not check if we are shutting down
cleanly (ata_flushcache() was copy-n-pasted from addump()) and always
uses atadev->channel->hw.begin_transaction(&request)/end_transaction(&request)
directly.

/fjoe

--PEIAKu/WMn1b1Hv9
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment; filename="ata.diff"

Index: ata-all.c
===================================================================
RCS file: /home/ncvs/src/sys/dev/ata/ata-all.c,v
retrieving revision 1.222.2.7
diff -u -p -r1.222.2.7 ata-all.c
--- ata-all.c	2 Mar 2005 02:15:13 -0000	1.222.2.7
+++ ata-all.c	16 Mar 2005 05:09:04 -0000
@@ -66,6 +66,7 @@ static struct cdevsw ata_cdevsw = {
 };
 
 /* prototypes */
+static void ata_flushcache(struct ata_device *);
 static void ata_shutdown(void *, int);
 static void ata_interrupt(void *);
 static int ata_getparam(struct ata_device *, u_int8_t);
@@ -373,6 +374,29 @@ ata_resume(device_t dev)
 }
 
 static void
+ata_flushcache(struct ata_device *atadev)
+{
+    struct ata_request request;
+
+    if (panicstr == NULL) {
+	ata_controlcmd(atadev, ATA_FLUSHCACHE, 0, 0, 0);
+	return;
+    }
+
+    bzero(&request, sizeof(struct ata_request));
+    request.device = atadev;
+    request.u.ata.command = ATA_FLUSHCACHE;
+    request.flags = ATA_R_CONTROL;
+
+    if (atadev->channel->hw.begin_transaction(&request) == ATA_OP_CONTINUES) {
+	do {
+	    DELAY(20);
+	} while (atadev->channel->hw.end_transaction(&request) == ATA_OP_CONTINUES);
+	ata_finish(&request);
+    }
+}
+
+static void
 ata_shutdown(void *arg, int howto)
 {
     struct ata_channel *ch;
@@ -384,10 +408,10 @@ ata_shutdown(void *arg, int howto)
 	    continue;
 	if (ch->device[MASTER].param &&
 	    ch->device[MASTER].param->support.command2 & ATA_SUPPORT_FLUSHCACHE)
-	    ata_controlcmd(&ch->device[MASTER], ATA_FLUSHCACHE, 0, 0, 0);
+	    ata_flushcache(&ch->device[MASTER]);
 	if (ch->device[SLAVE].param &&
 	    ch->device[SLAVE].param->support.command2 & ATA_SUPPORT_FLUSHCACHE)
-	    ata_controlcmd(&ch->device[SLAVE], ATA_FLUSHCACHE, 0, 0, 0);
+	    ata_flushcache(&ch->device[SLAVE]);
     }
 }
 

--PEIAKu/WMn1b1Hv9--



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