diff options
author | Samuel Thibault <samuel.thibault@ens-lyon.org> | 2013-06-09 22:05:02 +0200 |
---|---|---|
committer | Samuel Thibault <samuel.thibault@ens-lyon.org> | 2013-06-09 22:05:02 +0200 |
commit | b6f5f510249eaa3cdc31fd7d001f61b7844dbee0 (patch) | |
tree | a9bc9bdafcc2f10c4ea393e2ae329f8c12b11a28 /linux/dev/drivers/block/ahci.c | |
parent | b582af37cf8bfd70e6cf9a0e082b26890e8108af (diff) |
Add timeout to ahci IDENTIFY
* linux/dev/drivers/block/ahci.c (identify_timeout): New function.
(identify_timer): New variable.
(ahci_probe_port): Add timer to abandon identify command.
Diffstat (limited to 'linux/dev/drivers/block/ahci.c')
-rw-r--r-- | linux/dev/drivers/block/ahci.c | 16 |
1 files changed, 15 insertions, 1 deletions
diff --git a/linux/dev/drivers/block/ahci.c b/linux/dev/drivers/block/ahci.c index 88b2ab8..a9d6335 100644 --- a/linux/dev/drivers/block/ahci.c +++ b/linux/dev/drivers/block/ahci.c @@ -514,6 +514,15 @@ static struct file_operations ahci_fops = { .revalidate = NULL, }; +/* Disk timed out while processing identify, interrupt ahci_probe_port */ +static void identify_timeout(unsigned long data) +{ + struct port *port = (void*) data; + + wake_up(&port->q); +} + +static struct timer_list identify_timer = { .function = identify_timeout }; /* Probe one AHCI port */ static void ahci_probe_port(const volatile struct ahci_host *ahci_host, const volatile struct ahci_port *ahci_port) @@ -671,15 +680,20 @@ static void ahci_probe_port(const volatile struct ahci_host *ahci_host, const vo writel(1 << slot, &ahci_port->ci); timeout = jiffies + WAIT_MAX; + identify_timer.expires = timeout; + identify_timer.data = (unsigned long) port; + add_timer(&identify_timer); while (!port->status) { - if (jiffies > timeout) { + if (jiffies >= timeout) { printk("sd%u: timeout waiting for ready\n", port-ports); port->ahci_host = NULL; port->ahci_port = NULL; + del_timer(&identify_timer); return; } sleep_on(&port->q); } + del_timer(&identify_timer); restore_flags(flags); if (readl(&ahci_port->is) & PORT_IRQ_TF_ERR) |