Peter J. Philipp recently ran into this on his Intel AHCI+Intel SSD
system (see misc from yesterday):

ahci2 at pci0 dev 31 function 2 "Intel 8 Series AHCI" rev 0x05: msi, AHCI 1.3
ahci2: device on port 1 didn't come ready, TFD: 0x80<BSY>
ahci2: stopping the port, softreset slot 31 was still active.
ahci2: unable to communicate with device on port 1

I've seen this on boot with Intel AHCI and Transcend SSD and others
have seen it with Intel AHCI+Intel SSD on soekris net6501.

Here's a simple fix based on Dragonfly's fix for the same problem.
(Try to restablish communication one more time.)

http://gitweb.dragonflybsd.org/dragonfly.git/commitdiff/f2dba7003b2add226b3999a41a99fd278cc5a26f

Dragonfly will only reset here on startup, whereas OpenBSD will
call this to reset ports after startup. This symptom occurred to
me during >24 hour heavy 100% read+write utilization on softraid
RAID1 configuration, with regular SATA disks. So if we are going 
to call ahci_port_portreset during operation, this seems prudent.

Index: ahci.c
===================================================================
RCS file: /cvs/src/sys/dev/ic/ahci.c,v
retrieving revision 1.13
diff -u -r1.13 ahci.c
--- ahci.c      14 Apr 2014 04:42:22 -0000      1.13
+++ ahci.c      23 Apr 2014 14:11:16 -0000
@@ -1363,7 +1363,7 @@
 ahci_port_portreset(struct ahci_port *ap, int pmp)
 {
        u_int32_t                       cmd, r;
-       int                             rc, s;
+       int                             rc, s, retries = 0;
 
        s = splbio();
        DPRINTF(AHCI_D_VERBOSE, "%s: port reset\n", PORTNAME(ap));
@@ -1378,6 +1378,10 @@
        ahci_pwrite(ap, AHCI_PREG_SCTL, 0);
        delay(10000);
        r = AHCI_PREG_SCTL_IPM_DISABLED | AHCI_PREG_SCTL_DET_INIT;
+
+       ahci_pwrite(ap, AHCI_PREG_SCTL, r);
+retry:
+       delay(10000);
        if ((ap->ap_sc->sc_dev.dv_cfdata->cf_flags & 0x01) != 0) {
                DPRINTF(AHCI_D_VERBOSE, "%s: forcing GEN1\n", PORTNAME(ap));
                r |= AHCI_PREG_SCTL_SPD_GEN1;
@@ -1411,6 +1415,10 @@
                        /* even if the device doesn't wake up, check if there's
                         * a port multiplier there
                         */
+                       if (retries == 0) {
+                               retries = 1;
+                               goto retry;
+                       }
                        rc = EBUSY;
                } else {
                        rc = 0;

Reply via email to