kern/183294: VIA VX900 - SATA hang

Alexandre Martins alexandre.martins at netasq.com
Fri Oct 25 07:30:00 UTC 2013


>Number:         183294
>Category:       kern
>Synopsis:       VIA VX900 - SATA hang
>Confidential:   no
>Severity:       non-critical
>Priority:       low
>Responsible:    freebsd-bugs
>State:          open
>Quarter:        
>Keywords:       
>Date-Required:
>Class:          sw-bug
>Submitter-Id:   current-users
>Arrival-Date:   Fri Oct 25 07:30:00 UTC 2013
>Closed-Date:
>Last-Modified:
>Originator:     Alexandre Martins
>Release:        RELEASE 9.2
>Organization:
NETASQ
>Environment:
FreeBSD machine.netasq.com 9.2-RELEASE FreeBSD 9.2-RELEASE #0: Wed Sep 25 11:48:26 CEST 2013     alexandrem at machine.netasq.com:/usr/obj/usr/src/sys/GENERIC i386
>Description:
The VIA VX900, SATA controler, hang during its initialization, resulting hard drives not seen by kernel.

The hang is due to the reset commands that not wait previous reset command completion.

Depending on the speed of the hard drive initilization, the reset command can take more time.
>How-To-Repeat:
It's depending on how many and the kind of hard drives drive plugged.
>Fix:
Wait the controller have finished the reset command before send another one.

The attached patch show two kinds of waiting, but i don't know which is the better one.

Patch attached with submission follows:

--- dev/ata/chipsets/ata-via.c.orig	2013-10-24 09:32:45.000000000 +0000
+++ dev/ata/chipsets/ata-via.c	2013-10-24 09:39:51.000000000 +0000
@@ -459,6 +459,7 @@
 		devs = ata_sata_phy_reset(dev, 0, 0);
 		DELAY(10000);
 		devs += ata_sata_phy_reset(dev, 1, 0);
+		DELAY(10000);
 	} else
 		devs = 1;
 	if (devs)
--- dev/ata/chipsets/ata-via.c.orig	2013-10-24 13:39:17.000000000 +0000
+++ dev/ata/chipsets/ata-via.c	2013-10-24 09:24:04.000000000 +0000
@@ -456,11 +456,29 @@
 {
 	struct ata_channel *ch = device_get_softc(dev);
 	int devs;
+	u_int8_t status;
+	int count;
 
 	if (ch->unit == 0) {
 		devs = ata_sata_phy_reset(dev, 0, 0);
-		DELAY(10000);
+		count = 0;
+		do
+		{
+			ATA_IDX_OUTB(ch, ATA_DRIVE, ATA_D_IBM | ATA_D_LBA | ATA_DEV(ATA_MASTER));
+			DELAY(1000);
+			status = ATA_IDX_INB(ch, ATA_STATUS);
+			count++;
+		} while (status & ATA_S_BUSY && count < 100);
+
 		devs += ata_sata_phy_reset(dev, 1, 0);
+		count = 0;
+		do
+		{
+			ATA_IDX_OUTB(ch, ATA_DRIVE, ATA_D_IBM | ATA_D_LBA | ATA_DEV(ATA_SLAVE));
+			DELAY(1000);
+			status = ATA_IDX_INB(ch, ATA_STATUS);
+			count++;
+		} while (status & ATA_S_BUSY && count < 100);
 	} else
 		devs = 1;
 	if (devs)


>Release-Note:
>Audit-Trail:
>Unformatted:


More information about the freebsd-bugs mailing list