kern/129784: [patch] SATA port multiplier disk detect bugs in
-current (svn186316)
James R. Van Artsdalen
james at jrv.org
Sat Dec 20 02:30:01 PST 2008
>Number: 129784
>Category: kern
>Synopsis: [patch] SATA port multiplier disk detect bugs in -current (svn186316)
>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: Sat Dec 20 10:30:00 UTC 2008
>Closed-Date:
>Last-Modified:
>Originator: James R. Van Artsdalen
>Release: FreeBSD 8 -current, svn186316
>Organization:
Institute for Applied Stellar Nucleosynthesis
>Environment:
System: FreeBSD fearless 8 -current svn186316 #0: Fri Dec 24 01:47:55 CST 2004 james at jrv.org:/usr/src/sys/amd64/compile/GENERIC amd64
>Description:
This only affects Silicon Image host controllers. It was only tested with a 3132.
I have found two bugs in the port multiplier code and a place where an added delay is both necessary and sufficient to make my setup work, even though I can't explain why.
With the included patch my setup, with a Sil3132 host controller, always detects the drives in my Sil3726 based port-multiplier enclosures. There are other problems trying to format and use the disks, but at least this may let people get past disk detection.
>How-To-Repeat:
Attach a port multiplier enclosure to a Silicon Image host adapter. Some or all disks in the enclosure may not be seen.
>Fix:
The first change in ata_siiprb_issue_cmd() increases the timeout count from 10,000 to 31,000 counts. When a soft reset is issued to a port multiplier disk port this loop may have to wait for the hard disk to spin up. I consistently saw 15,000 counts as needed by experiment; assuming counts are milliseconds then 31,000 is what ATA calls for. Note that currently empty disk ports behind a port multiplier are detected by letting this loop time out; i.e., an empty port multiplier enclosure can lengthen boot by 2.5 minutes. Some other strategy for disk detection might be needed later (the PHY probably is a good approach).
The second change in ata_siiprb_issue_cmd() fixes a typo: failure was being returned if a command took more than 1,000 counts, even if it completed within the allotted 10,000 counts.
The last change in ata_siiprb_softreset() is a delay that is mysteriously turns out to be necessary. I don't know why, how much or how little is needed. Hardware is like that sometimes.
/usr/src-current# svn di
Index: sys/dev/ata/chipsets/ata-siliconimage.c
===================================================================
--- sys/dev/ata/chipsets/ata-siliconimage.c (revision 186316)
+++ sys/dev/ata/chipsets/ata-siliconimage.c (working copy)
@@ -679,7 +679,7 @@
ATA_OUTL(ctlr->r_res2, 0x1c04 + offset, prb_bus >> 32);
/* poll for command finished */
- for (timeout = 0; timeout < 10000; timeout++) {
+ for (timeout = 0; timeout < 31000; timeout++) {
DELAY(1000);
if ((status = ATA_INL(ctlr->r_res2, 0x1008 + offset)) & 0x00010000)
break;
@@ -687,7 +687,7 @@
// SOS XXX ATA_OUTL(ctlr->r_res2, 0x1008 + offset, 0x00010000);
ATA_OUTL(ctlr->r_res2, 0x1008 + offset, 0x08ff08ff);
- if (timeout >= 1000)
+ if (timeout >= 31000)
return EIO;
if (bootverbose)
@@ -761,6 +761,18 @@
prb->control = htole16(0x0080);
prb->fis[1] = port & 0x0f;
+ ata_udelay(150000);
+ ata_udelay(150000);
+ ata_udelay(150000);
+ ata_udelay(150000);
+ ata_udelay(150000);
+ ata_udelay(150000);
+ ata_udelay(150000);
+ ata_udelay(150000);
+ ata_udelay(150000);
+ ata_udelay(150000);
+ ata_udelay(150000);
+
/* issue soft reset */
if (ata_siiprb_issue_cmd(dev))
return -1;
/usr/src-current#
>Release-Note:
>Audit-Trail:
>Unformatted:
More information about the freebsd-bugs
mailing list