ahci: rewrite timeout initialization code

- the "ahci_sig_timeout" variable now denotes the entire checking
  period, and the delay between checks has been hardcoded; what was
  previously "ahci_sig_checks" is now computed from those two;
- timeout values are no longer used for both millisecond and clock
  tick values, and better typed;
- the computation of timeouts is no longer off by half a second.
This commit is contained in:
David van Moolenbroek 2013-02-12 13:53:09 +00:00
parent ad0b58fe83
commit 23b12e29a2
2 changed files with 42 additions and 33 deletions

View file

@ -181,13 +181,27 @@ static int ahci_instance; /* driver instance number */
static int ahci_verbose; /* verbosity level (0..4) */
/* Timeout values. These can be overridden with environment variables. */
static long ahci_spinup_timeout = SPINUP_TIMEOUT;
static long ahci_sig_timeout = SIG_TIMEOUT;
static long ahci_sig_checks = NR_SIG_CHECKS;
static long ahci_command_timeout = COMMAND_TIMEOUT;
static long ahci_transfer_timeout = TRANSFER_TIMEOUT;
static long ahci_flush_timeout = FLUSH_TIMEOUT;
/* Timeout-related values. */
static clock_t ahci_spinup_timeout;
static clock_t ahci_sig_timeout;
static clock_t ahci_sig_delay;
static unsigned int ahci_sig_checks;
static clock_t ahci_command_timeout;
static clock_t ahci_transfer_timeout;
static clock_t ahci_flush_timeout;
/* Timeout environment variable names and default values. */
static struct {
char *name; /* environment variable name */
u32_t default_ms; /* default in milliseconds */
clock_t *ptr; /* clock ticks value pointer */
} ahci_timevar[] = {
{ "ahci_init_timeout", SPINUP_TIMEOUT, &ahci_spinup_timeout },
{ "ahci_sig_timeout", SIG_TIMEOUT, &ahci_sig_timeout },
{ "ahci_cmd_timeout", COMMAND_TIMEOUT, &ahci_command_timeout },
{ "ahci_io_timeout", TRANSFER_TIMEOUT, &ahci_transfer_timeout },
{ "ahci_flush_timeout", FLUSH_TIMEOUT, &ahci_flush_timeout }
};
static int ahci_map[MAX_DRIVES]; /* device-to-port mapping */
@ -202,6 +216,9 @@ static int ahci_exiting = FALSE; /* exit after last close? */
printf s; \
} while (0)
/* Convert milliseconds to clock ticks. Round up. */
#define millis_to_hz(ms) (((ms) * sys_hz() + 999) / 1000)
static void port_set_cmd(struct port_state *ps, int cmd, cmd_fis_t *fis,
u8_t packet[ATAPI_PACKET_SIZE], prd_t *prdt, int nr_prds, int write);
static void port_issue(struct port_state *ps, int cmd, clock_t timeout);
@ -1330,7 +1347,7 @@ static void port_sig_check(struct port_state *ps)
/* Try for a while before giving up. It may take seconds. */
if (ps->left > 0) {
ps->left--;
set_timer(&ps->cmd_info[0].timer, ahci_sig_timeout,
set_timer(&ps->cmd_info[0].timer, ahci_sig_delay,
port_timeout, BUILD_ARG(ps - port_state, 0));
return;
}
@ -2142,23 +2159,6 @@ static void ahci_intr(unsigned int UNUSED(mask))
panic("unable to enable IRQ: %d", r);
}
/*===========================================================================*
* ahci_get_var *
*===========================================================================*/
static void ahci_get_var(char *name, long *v, int timeout)
{
/* Retrieve an environment variable, and optionall adjust it to the
* scale that we are using internally.
*/
/* The value is supposed to be initialized to a default already. */
(void) env_parse(name, "d", 0, v, 1, LONG_MAX);
/* If this is a timeout, convert from milliseconds to ticks. */
if (timeout)
*v = (*v + 500) * sys_hz() / 1000;
}
/*===========================================================================*
* ahci_get_params *
*===========================================================================*/
@ -2168,6 +2168,7 @@ static void ahci_get_params(void)
* device-to-port mapping, which has to be parsed later.
*/
long v;
int i;
/* Find out which driver instance we are. */
v = 0;
@ -2180,12 +2181,18 @@ static void ahci_get_params(void)
ahci_verbose = (int) v;
/* Initialize timeout-related values. */
ahci_get_var("ahci_init_timeout", &ahci_spinup_timeout, TRUE);
ahci_get_var("ahci_sig_timeout", &ahci_sig_timeout, TRUE);
ahci_get_var("ahci_sig_checks", &ahci_sig_checks, FALSE);
ahci_get_var("ahci_cmd_timeout", &ahci_command_timeout, TRUE);
ahci_get_var("ahci_io_timeout", &ahci_transfer_timeout, TRUE);
ahci_get_var("ahci_flush_timeout", &ahci_flush_timeout, TRUE);
for (i = 0; i < sizeof(ahci_timevar) / sizeof(ahci_timevar[0]); i++) {
v = ahci_timevar[i].default_ms;
(void) env_parse(ahci_timevar[i].name, "d", 0, &v, 1,
LONG_MAX);
*ahci_timevar[i].ptr = millis_to_hz(v);
}
ahci_sig_delay = millis_to_hz(SIG_DELAY);
ahci_sig_checks =
(ahci_sig_timeout + ahci_sig_delay - 1) / ahci_sig_delay;
}
/*===========================================================================*

View file

@ -8,8 +8,7 @@
/* Time values that can be set with options. */
#define SPINUP_TIMEOUT 5000 /* initial spin-up time (ms) */
#define SIG_TIMEOUT 250 /* time between signature checks (ms) */
#define NR_SIG_CHECKS 60 /* maximum number of times to check */
#define SIG_TIMEOUT 15000 /* time to wait for signature (ms) */
#define COMMAND_TIMEOUT 10000 /* time to wait for non-I/O cmd (ms) */
#define TRANSFER_TIMEOUT 30000 /* time to wait for I/O cmd (ms) */
#define FLUSH_TIMEOUT 60000 /* time to wait for flush cmd (ms) */
@ -19,6 +18,9 @@
#define RESET_DELAY 1000 /* maximum HBA reset time (ms) */
#define PORTREG_DELAY 500 /* maximum port register update (ms) */
/* Other hardcoded time values. */
#define SIG_DELAY 250 /* time between signature checks (ms) */
/* Generic FIS layout. */
#define ATA_FIS_TYPE 0 /* FIS Type */
#define ATA_FIS_TYPE_H2D 0x27 /* Register - Host to Device */