summaryrefslogtreecommitdiff
path: root/linux/dev
diff options
context:
space:
mode:
authorSamuel Thibault <samuel.thibault@ens-lyon.org>2013-06-09 22:05:02 +0200
committerSamuel Thibault <samuel.thibault@ens-lyon.org>2013-06-09 22:05:02 +0200
commitb6f5f510249eaa3cdc31fd7d001f61b7844dbee0 (patch)
treea9bc9bdafcc2f10c4ea393e2ae329f8c12b11a28 /linux/dev
parentb582af37cf8bfd70e6cf9a0e082b26890e8108af (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')
-rw-r--r--linux/dev/drivers/block/ahci.c16
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)