]> Zhao Yanbai Git Server - minix.git/commitdiff
ahci: centralize, fix port reset
authorDavid van Moolenbroek <david@minix3.org>
Tue, 12 Feb 2013 13:52:52 +0000 (13:52 +0000)
committerDavid van Moolenbroek <david@minix3.org>
Tue, 12 Feb 2013 13:52:52 +0000 (13:52 +0000)
drivers/ahci/ahci.c
drivers/ahci/ahci.h

index c04e41bedf7ace50a8ed1ab69c17475680a7a7ab..bbb47efddf2055dc85d5a7f4eb9d2e9b5d57a09f 100644 (file)
@@ -1192,6 +1192,21 @@ static ssize_t port_transfer(struct port_state *ps, u64_t pos, u64_t eof,
        return size;
 }
 
+/*===========================================================================*
+ *                             port_hardreset                               *
+ *===========================================================================*/
+static void port_hardreset(struct port_state *ps)
+{
+       /* Perform a port-level (hard) reset on the given port.
+        */
+
+       port_write(ps, AHCI_PORT_SCTL, AHCI_PORT_SCTL_DET_INIT);
+
+       micro_delay(COMRESET_DELAY * 1000);     /* COMRESET_DELAY is in ms */
+
+       port_write(ps, AHCI_PORT_SCTL, AHCI_PORT_SCTL_DET_NONE);
+}
+
 /*===========================================================================*
  *                             port_start                                   *
  *===========================================================================*/
@@ -1242,20 +1257,18 @@ static void port_restart(struct port_state *ps)
 
                dprintf(V_ERR, ("%s: port reset\n", ahci_portname(ps)));
 
-               /* Trigger a port reset. */
-               port_write(ps, AHCI_PORT_SCTL, AHCI_PORT_SCTL_DET_INIT);
-               micro_delay(SPINUP_DELAY * 1000);
-               port_write(ps, AHCI_PORT_SCTL, AHCI_PORT_SCTL_DET_NONE);
-
                /* To keep this driver simple, we do not transparently recover
                 * ongoing requests. Instead, we mark the failing device as
-                * disconnected, and assume that if the reset succeeds, the
+                * disconnected, and reset it. If the reset succeeds, the
                 * device (or, perhaps, eventually, another device) will come
                 * back up. Any current and future requests to this port will
                 * be failed until the port is fully closed and reopened.
                 */
                port_disconnect(ps);
 
+               /* Trigger a port reset. */
+               port_hardreset(ps);
+
                return;
        }
 
@@ -1907,13 +1920,14 @@ static void port_init(struct port_state *ps)
        /* Just listen for device status change events for now. */
        port_write(ps, AHCI_PORT_IE, AHCI_PORT_IE_PRCE);
 
-       /* Perform a reset on the device. */
+       /* Enable device spin-up for HBAs that support staggered spin-up.
+        * This is a no-op for HBAs that do not support it.
+        */
        cmd = port_read(ps, AHCI_PORT_CMD);
        port_write(ps, AHCI_PORT_CMD, cmd | AHCI_PORT_CMD_SUD);
 
-       port_write(ps, AHCI_PORT_SCTL, AHCI_PORT_SCTL_DET_INIT);
-       micro_delay(SPINUP_DELAY * 1000);       /* SPINUP_DELAY is in ms */
-       port_write(ps, AHCI_PORT_SCTL, AHCI_PORT_SCTL_DET_NONE);
+       /* Trigger a port reset. */
+       port_hardreset(ps);
 
        set_timer(&ps->cmd_info[0].timer, ahci_spinup_timeout,
                port_timeout, BUILD_ARG(ps - port_state, 0));
index 617619338135e653381c649396464713160a9c4b..48b5f5318bb2eff7dedb6a57d23c6cfadcad9887 100644 (file)
@@ -15,7 +15,7 @@
 #define FLUSH_TIMEOUT          60000   /* time to wait for flush cmd (ms) */
 
 /* Time values that are defined by the standards. */
-#define SPINUP_DELAY           1       /* time to assert spin-up flag (ms) */
+#define COMRESET_DELAY         1       /* time to assert port reset (ms) */
 #define RESET_DELAY            1000    /* maximum HBA reset time (ms) */
 #define PORTREG_DELAY          500     /* maximum port register update (ms) */