aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
authorAlan Cox <alan@redhat.com>2009-03-24 06:23:46 -0400
committerJeff Garzik <jgarzik@redhat.com>2009-03-24 22:52:39 -0400
commitc96f1732e25362d10ee7bcac1df8412a2e6b7d23 (patch)
tree66e24eddb174d6751579ec5952f72cbbac0fb038 /drivers
parent3d47aa8e7e7b2aa09256590388aa8dddc79280f9 (diff)
[libata] Improve timeout handling
On a timeout call a device specific handler early in the recovery so that we can complete and process successful commands which timed out due to IRQ loss or the like rather more elegantly. [Revised to exclude the timeout handling on a few devices that inherit from SFF but are not SFF enough to use the default timeout handler] Signed-off-by: Alan Cox <alan@redhat.com> Signed-off-by: Jeff Garzik <jgarzik@redhat.com>
Diffstat (limited to 'drivers')
-rw-r--r--drivers/ata/libata-eh.c19
-rw-r--r--drivers/ata/libata-sff.c46
-rw-r--r--drivers/ata/pata_isapnp.c12
-rw-r--r--drivers/ata/pdc_adma.c2
-rw-r--r--drivers/ata/sata_mv.c2
-rw-r--r--drivers/ata/sata_nv.c1
-rw-r--r--drivers/ata/sata_promise.c2
-rw-r--r--drivers/ata/sata_qstor.c1
-rw-r--r--drivers/ata/sata_vsc.c3
9 files changed, 83 insertions, 5 deletions
diff --git a/drivers/ata/libata-eh.c b/drivers/ata/libata-eh.c
index ea890911d4fa..01831312c360 100644
--- a/drivers/ata/libata-eh.c
+++ b/drivers/ata/libata-eh.c
@@ -547,7 +547,7 @@ void ata_scsi_error(struct Scsi_Host *host)
547 547
548 /* For new EH, all qcs are finished in one of three ways - 548 /* For new EH, all qcs are finished in one of three ways -
549 * normal completion, error completion, and SCSI timeout. 549 * normal completion, error completion, and SCSI timeout.
550 * Both cmpletions can race against SCSI timeout. When normal 550 * Both completions can race against SCSI timeout. When normal
551 * completion wins, the qc never reaches EH. When error 551 * completion wins, the qc never reaches EH. When error
552 * completion wins, the qc has ATA_QCFLAG_FAILED set. 552 * completion wins, the qc has ATA_QCFLAG_FAILED set.
553 * 553 *
@@ -562,7 +562,19 @@ void ata_scsi_error(struct Scsi_Host *host)
562 int nr_timedout = 0; 562 int nr_timedout = 0;
563 563
564 spin_lock_irqsave(ap->lock, flags); 564 spin_lock_irqsave(ap->lock, flags);
565 565
566 /* This must occur under the ap->lock as we don't want
567 a polled recovery to race the real interrupt handler
568
569 The lost_interrupt handler checks for any completed but
570 non-notified command and completes much like an IRQ handler.
571
572 We then fall into the error recovery code which will treat
573 this as if normal completion won the race */
574
575 if (ap->ops->lost_interrupt)
576 ap->ops->lost_interrupt(ap);
577
566 list_for_each_entry_safe(scmd, tmp, &host->eh_cmd_q, eh_entry) { 578 list_for_each_entry_safe(scmd, tmp, &host->eh_cmd_q, eh_entry) {
567 struct ata_queued_cmd *qc; 579 struct ata_queued_cmd *qc;
568 580
@@ -606,6 +618,9 @@ void ata_scsi_error(struct Scsi_Host *host)
606 ap->eh_tries = ATA_EH_MAX_TRIES; 618 ap->eh_tries = ATA_EH_MAX_TRIES;
607 } else 619 } else
608 spin_unlock_wait(ap->lock); 620 spin_unlock_wait(ap->lock);
621
622 /* If we timed raced normal completion and there is nothing to
623 recover nr_timedout == 0 why exactly are we doing error recovery ? */
609 624
610 repeat: 625 repeat:
611 /* invoke error handler */ 626 /* invoke error handler */
diff --git a/drivers/ata/libata-sff.c b/drivers/ata/libata-sff.c
index 9a10cb055ac2..8332e97a9de3 100644
--- a/drivers/ata/libata-sff.c
+++ b/drivers/ata/libata-sff.c
@@ -65,6 +65,8 @@ const struct ata_port_operations ata_sff_port_ops = {
65 .sff_irq_on = ata_sff_irq_on, 65 .sff_irq_on = ata_sff_irq_on,
66 .sff_irq_clear = ata_sff_irq_clear, 66 .sff_irq_clear = ata_sff_irq_clear,
67 67
68 .lost_interrupt = ata_sff_lost_interrupt,
69
68 .port_start = ata_sff_port_start, 70 .port_start = ata_sff_port_start,
69}; 71};
70EXPORT_SYMBOL_GPL(ata_sff_port_ops); 72EXPORT_SYMBOL_GPL(ata_sff_port_ops);
@@ -1647,7 +1649,7 @@ EXPORT_SYMBOL_GPL(ata_sff_qc_fill_rtf);
1647 * RETURNS: 1649 * RETURNS:
1648 * One if interrupt was handled, zero if not (shared irq). 1650 * One if interrupt was handled, zero if not (shared irq).
1649 */ 1651 */
1650inline unsigned int ata_sff_host_intr(struct ata_port *ap, 1652unsigned int ata_sff_host_intr(struct ata_port *ap,
1651 struct ata_queued_cmd *qc) 1653 struct ata_queued_cmd *qc)
1652{ 1654{
1653 struct ata_eh_info *ehi = &ap->link.eh_info; 1655 struct ata_eh_info *ehi = &ap->link.eh_info;
@@ -1776,6 +1778,48 @@ irqreturn_t ata_sff_interrupt(int irq, void *dev_instance)
1776EXPORT_SYMBOL_GPL(ata_sff_interrupt); 1778EXPORT_SYMBOL_GPL(ata_sff_interrupt);
1777 1779
1778/** 1780/**
1781 * ata_sff_lost_interrupt - Check for an apparent lost interrupt
1782 * @ap: port that appears to have timed out
1783 *
1784 * Called from the libata error handlers when the core code suspects
1785 * an interrupt has been lost. If it has complete anything we can and
1786 * then return. Interface must support altstatus for this faster
1787 * recovery to occur.
1788 *
1789 * Locking:
1790 * Caller holds host lock
1791 */
1792
1793void ata_sff_lost_interrupt(struct ata_port *ap)
1794{
1795 u8 status;
1796 struct ata_queued_cmd *qc;
1797
1798 /* Only one outstanding command per SFF channel */
1799 qc = ata_qc_from_tag(ap, ap->link.active_tag);
1800 /* Check we have a live one.. */
1801 if (qc == NULL || !(qc->flags & ATA_QCFLAG_ACTIVE))
1802 return;
1803 /* We cannot lose an interrupt on a polled command */
1804 if (qc->tf.flags & ATA_TFLAG_POLLING)
1805 return;
1806 /* See if the controller thinks it is still busy - if so the command
1807 isn't a lost IRQ but is still in progress */
1808 status = ata_sff_altstatus(ap);
1809 if (status & ATA_BUSY)
1810 return;
1811
1812 /* There was a command running, we are no longer busy and we have
1813 no interrupt. */
1814 ata_port_printk(ap, KERN_WARNING, "lost interrupt (Status 0x%x)\n",
1815 status);
1816 /* Run the host interrupt logic as if the interrupt had not been
1817 lost */
1818 ata_sff_host_intr(ap, qc);
1819}
1820EXPORT_SYMBOL_GPL(ata_sff_lost_interrupt);
1821
1822/**
1779 * ata_sff_freeze - Freeze SFF controller port 1823 * ata_sff_freeze - Freeze SFF controller port
1780 * @ap: port to freeze 1824 * @ap: port to freeze
1781 * 1825 *
diff --git a/drivers/ata/pata_isapnp.c b/drivers/ata/pata_isapnp.c
index afa8f704271e..4bceb8803a10 100644
--- a/drivers/ata/pata_isapnp.c
+++ b/drivers/ata/pata_isapnp.c
@@ -17,7 +17,7 @@
17#include <linux/libata.h> 17#include <linux/libata.h>
18 18
19#define DRV_NAME "pata_isapnp" 19#define DRV_NAME "pata_isapnp"
20#define DRV_VERSION "0.2.2" 20#define DRV_VERSION "0.2.5"
21 21
22static struct scsi_host_template isapnp_sht = { 22static struct scsi_host_template isapnp_sht = {
23 ATA_PIO_SHT(DRV_NAME), 23 ATA_PIO_SHT(DRV_NAME),
@@ -28,6 +28,13 @@ static struct ata_port_operations isapnp_port_ops = {
28 .cable_detect = ata_cable_40wire, 28 .cable_detect = ata_cable_40wire,
29}; 29};
30 30
31static struct ata_port_operations isapnp_noalt_port_ops = {
32 .inherits = &ata_sff_port_ops,
33 .cable_detect = ata_cable_40wire,
34 /* No altstatus so we don't want to use the lost interrupt poll */
35 .lost_interrupt = ATA_OP_NULL,
36};
37
31/** 38/**
32 * isapnp_init_one - attach an isapnp interface 39 * isapnp_init_one - attach an isapnp interface
33 * @idev: PnP device 40 * @idev: PnP device
@@ -65,7 +72,7 @@ static int isapnp_init_one(struct pnp_dev *idev, const struct pnp_device_id *dev
65 72
66 ap = host->ports[0]; 73 ap = host->ports[0];
67 74
68 ap->ops = &isapnp_port_ops; 75 ap->ops = &isapnp_noalt_port_ops;
69 ap->pio_mask = ATA_PIO0; 76 ap->pio_mask = ATA_PIO0;
70 ap->flags |= ATA_FLAG_SLAVE_POSS; 77 ap->flags |= ATA_FLAG_SLAVE_POSS;
71 78
@@ -76,6 +83,7 @@ static int isapnp_init_one(struct pnp_dev *idev, const struct pnp_device_id *dev
76 pnp_port_start(idev, 1), 1); 83 pnp_port_start(idev, 1), 1);
77 ap->ioaddr.altstatus_addr = ctl_addr; 84 ap->ioaddr.altstatus_addr = ctl_addr;
78 ap->ioaddr.ctl_addr = ctl_addr; 85 ap->ioaddr.ctl_addr = ctl_addr;
86 ap->ops = &isapnp_port_ops;
79 } 87 }
80 88
81 ata_sff_std_ports(&ap->ioaddr); 89 ata_sff_std_ports(&ap->ioaddr);
diff --git a/drivers/ata/pdc_adma.c b/drivers/ata/pdc_adma.c
index c509c206a459..39588178d028 100644
--- a/drivers/ata/pdc_adma.c
+++ b/drivers/ata/pdc_adma.c
@@ -148,6 +148,8 @@ static struct scsi_host_template adma_ata_sht = {
148static struct ata_port_operations adma_ata_ops = { 148static struct ata_port_operations adma_ata_ops = {
149 .inherits = &ata_sff_port_ops, 149 .inherits = &ata_sff_port_ops,
150 150
151 .lost_interrupt = ATA_OP_NULL,
152
151 .check_atapi_dma = adma_check_atapi_dma, 153 .check_atapi_dma = adma_check_atapi_dma,
152 .qc_prep = adma_qc_prep, 154 .qc_prep = adma_qc_prep,
153 .qc_issue = adma_qc_issue, 155 .qc_issue = adma_qc_issue,
diff --git a/drivers/ata/sata_mv.c b/drivers/ata/sata_mv.c
index 8a751054c8a1..a377226b81c8 100644
--- a/drivers/ata/sata_mv.c
+++ b/drivers/ata/sata_mv.c
@@ -646,6 +646,8 @@ static struct scsi_host_template mv6_sht = {
646static struct ata_port_operations mv5_ops = { 646static struct ata_port_operations mv5_ops = {
647 .inherits = &ata_sff_port_ops, 647 .inherits = &ata_sff_port_ops,
648 648
649 .lost_interrupt = ATA_OP_NULL,
650
649 .qc_defer = mv_qc_defer, 651 .qc_defer = mv_qc_defer,
650 .qc_prep = mv_qc_prep, 652 .qc_prep = mv_qc_prep,
651 .qc_issue = mv_qc_issue, 653 .qc_issue = mv_qc_issue,
diff --git a/drivers/ata/sata_nv.c b/drivers/ata/sata_nv.c
index 2f523f8c27f6..6cda12ba8122 100644
--- a/drivers/ata/sata_nv.c
+++ b/drivers/ata/sata_nv.c
@@ -408,6 +408,7 @@ static struct scsi_host_template nv_swncq_sht = {
408 408
409static struct ata_port_operations nv_common_ops = { 409static struct ata_port_operations nv_common_ops = {
410 .inherits = &ata_bmdma_port_ops, 410 .inherits = &ata_bmdma_port_ops,
411 .lost_interrupt = ATA_OP_NULL,
411 .scr_read = nv_scr_read, 412 .scr_read = nv_scr_read,
412 .scr_write = nv_scr_write, 413 .scr_write = nv_scr_write,
413}; 414};
diff --git a/drivers/ata/sata_promise.c b/drivers/ata/sata_promise.c
index 3ad2b8863636..b1fd7d62071a 100644
--- a/drivers/ata/sata_promise.c
+++ b/drivers/ata/sata_promise.c
@@ -176,7 +176,9 @@ static const struct ata_port_operations pdc_common_ops = {
176 .check_atapi_dma = pdc_check_atapi_dma, 176 .check_atapi_dma = pdc_check_atapi_dma,
177 .qc_prep = pdc_qc_prep, 177 .qc_prep = pdc_qc_prep,
178 .qc_issue = pdc_qc_issue, 178 .qc_issue = pdc_qc_issue,
179
179 .sff_irq_clear = pdc_irq_clear, 180 .sff_irq_clear = pdc_irq_clear,
181 .lost_interrupt = ATA_OP_NULL,
180 182
181 .post_internal_cmd = pdc_post_internal_cmd, 183 .post_internal_cmd = pdc_post_internal_cmd,
182 .error_handler = pdc_error_handler, 184 .error_handler = pdc_error_handler,
diff --git a/drivers/ata/sata_qstor.c b/drivers/ata/sata_qstor.c
index 7112d89fd9ff..c3936d35cdac 100644
--- a/drivers/ata/sata_qstor.c
+++ b/drivers/ata/sata_qstor.c
@@ -147,6 +147,7 @@ static struct ata_port_operations qs_ata_ops = {
147 .softreset = ATA_OP_NULL, 147 .softreset = ATA_OP_NULL,
148 .error_handler = qs_error_handler, 148 .error_handler = qs_error_handler,
149 .post_internal_cmd = ATA_OP_NULL, 149 .post_internal_cmd = ATA_OP_NULL,
150 .lost_interrupt = ATA_OP_NULL,
150 151
151 .scr_read = qs_scr_read, 152 .scr_read = qs_scr_read,
152 .scr_write = qs_scr_write, 153 .scr_write = qs_scr_write,
diff --git a/drivers/ata/sata_vsc.c b/drivers/ata/sata_vsc.c
index ef211f333d7b..ed70bd28fa2c 100644
--- a/drivers/ata/sata_vsc.c
+++ b/drivers/ata/sata_vsc.c
@@ -308,6 +308,9 @@ static struct scsi_host_template vsc_sata_sht = {
308 308
309static struct ata_port_operations vsc_sata_ops = { 309static struct ata_port_operations vsc_sata_ops = {
310 .inherits = &ata_bmdma_port_ops, 310 .inherits = &ata_bmdma_port_ops,
311 /* The IRQ handling is not quite standard SFF behaviour so we
312 cannot use the default lost interrupt handler */
313 .lost_interrupt = ATA_OP_NULL,
311 .sff_tf_load = vsc_sata_tf_load, 314 .sff_tf_load = vsc_sata_tf_load,
312 .sff_tf_read = vsc_sata_tf_read, 315 .sff_tf_read = vsc_sata_tf_read,
313 .freeze = vsc_freeze, 316 .freeze = vsc_freeze,