diff options
author | Tejun Heo <htejun@gmail.com> | 2007-12-07 18:45:27 -0500 |
---|---|---|
committer | Jeff Garzik <jeff@garzik.org> | 2007-12-17 20:33:11 -0500 |
commit | 8cf32ac6578a70025be1103466da9d1d6141429e (patch) | |
tree | b77386f566db1d0a71bb0e7cbf2a69fd2ed9df5e /drivers/ata/sata_sil.c | |
parent | 2cc3a8f6ac0fb1e6095a47001d31aadcf9722bde (diff) |
sata_sil: fix spurious IRQ handling
Interestingly, sata_sil raises spurious interrupts if it's coupled
with Sil SATA_PATA bridge. Currently, sata_sil interrupt handler is
strict about spurious interrupts and freezes the port when it occurs.
This patch makes it more forgiving.
* On SATA PHY event interrupt, serror value is checked to see whether
it really is PHYRDY CHG event. If not, SATA PHY event interrupt is
ignored.
* If ATA interrupt occurs while no command is in progress, it's
cleared and ignored.
This fixes bugzilla bug 9505.
http://bugzilla.kernel.org/show_bug.cgi?id=9505
Signed-off-by: Tejun Heo <htejun@gmail.com>
Signed-off-by: Jeff Garzik <jeff@garzik.org>
Diffstat (limited to 'drivers/ata/sata_sil.c')
-rw-r--r-- | drivers/ata/sata_sil.c | 29 |
1 files changed, 17 insertions, 12 deletions
diff --git a/drivers/ata/sata_sil.c b/drivers/ata/sata_sil.c index 4e6e381279cc..025622b14efb 100644 --- a/drivers/ata/sata_sil.c +++ b/drivers/ata/sata_sil.c | |||
@@ -390,23 +390,28 @@ static void sil_host_intr(struct ata_port *ap, u32 bmdma2) | |||
390 | sil_scr_read(ap, SCR_ERROR, &serror); | 390 | sil_scr_read(ap, SCR_ERROR, &serror); |
391 | sil_scr_write(ap, SCR_ERROR, serror); | 391 | sil_scr_write(ap, SCR_ERROR, serror); |
392 | 392 | ||
393 | /* Trigger hotplug and accumulate SError only if the | 393 | /* Sometimes spurious interrupts occur, double check |
394 | * port isn't already frozen. Otherwise, PHY events | 394 | * it's PHYRDY CHG. |
395 | * during hardreset makes controllers with broken SIEN | ||
396 | * repeat probing needlessly. | ||
397 | */ | 395 | */ |
398 | if (!(ap->pflags & ATA_PFLAG_FROZEN)) { | 396 | if (serror & SERR_PHYRDY_CHG) { |
399 | ata_ehi_hotplugged(&ap->link.eh_info); | 397 | /* Trigger hotplug and accumulate SError only |
400 | ap->link.eh_info.serror |= serror; | 398 | * if the port isn't already frozen. |
399 | * Otherwise, PHY events during hardreset | ||
400 | * makes controllers with broken SIEN repeat | ||
401 | * probing needlessly. | ||
402 | */ | ||
403 | if (!(ap->pflags & ATA_PFLAG_FROZEN)) { | ||
404 | ata_ehi_hotplugged(&ap->link.eh_info); | ||
405 | ap->link.eh_info.serror |= serror; | ||
406 | } | ||
407 | goto freeze; | ||
401 | } | 408 | } |
402 | 409 | ||
403 | goto freeze; | 410 | if (!(bmdma2 & SIL_DMA_COMPLETE)) |
411 | return; | ||
404 | } | 412 | } |
405 | 413 | ||
406 | if (unlikely(!qc)) | 414 | if (unlikely(!qc || (qc->tf.flags & ATA_TFLAG_POLLING))) { |
407 | goto freeze; | ||
408 | |||
409 | if (unlikely(qc->tf.flags & ATA_TFLAG_POLLING)) { | ||
410 | /* this sometimes happens, just clear IRQ */ | 415 | /* this sometimes happens, just clear IRQ */ |
411 | ata_chk_status(ap); | 416 | ata_chk_status(ap); |
412 | return; | 417 | return; |