From: David van Moolenbroek Date: Tue, 12 Feb 2013 13:52:52 +0000 (+0000) Subject: ahci: centralize, fix port reset X-Git-Tag: v3.2.1~10 X-Git-Url: http://zhaoyanbai.com/repos/%22http:/www.isc.org/icons/zlib_tech.html?a=commitdiff_plain;h=ad0b58fe835b996b6eba9b6df83b2e35071ef126;p=minix.git ahci: centralize, fix port reset --- diff --git a/drivers/ahci/ahci.c b/drivers/ahci/ahci.c index c04e41bed..bbb47efdd 100644 --- a/drivers/ahci/ahci.c +++ b/drivers/ahci/ahci.c @@ -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)); diff --git a/drivers/ahci/ahci.h b/drivers/ahci/ahci.h index 617619338..48b5f5318 100644 --- a/drivers/ahci/ahci.h +++ b/drivers/ahci/ahci.h @@ -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) */