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>
This commit is contained in:
parent
2cc3a8f6ac
commit
8cf32ac657
|
@ -390,23 +390,28 @@ static void sil_host_intr(struct ata_port *ap, u32 bmdma2)
|
||||||
sil_scr_read(ap, SCR_ERROR, &serror);
|
sil_scr_read(ap, SCR_ERROR, &serror);
|
||||||
sil_scr_write(ap, SCR_ERROR, serror);
|
sil_scr_write(ap, SCR_ERROR, serror);
|
||||||
|
|
||||||
/* Trigger hotplug and accumulate SError only if the
|
/* Sometimes spurious interrupts occur, double check
|
||||||
* port isn't already frozen. Otherwise, PHY events
|
* it's PHYRDY CHG.
|
||||||
* during hardreset makes controllers with broken SIEN
|
*/
|
||||||
* repeat probing needlessly.
|
if (serror & SERR_PHYRDY_CHG) {
|
||||||
|
/* Trigger hotplug and accumulate SError only
|
||||||
|
* if the port isn't already frozen.
|
||||||
|
* Otherwise, PHY events during hardreset
|
||||||
|
* makes controllers with broken SIEN repeat
|
||||||
|
* probing needlessly.
|
||||||
*/
|
*/
|
||||||
if (!(ap->pflags & ATA_PFLAG_FROZEN)) {
|
if (!(ap->pflags & ATA_PFLAG_FROZEN)) {
|
||||||
ata_ehi_hotplugged(&ap->link.eh_info);
|
ata_ehi_hotplugged(&ap->link.eh_info);
|
||||||
ap->link.eh_info.serror |= serror;
|
ap->link.eh_info.serror |= serror;
|
||||||
}
|
}
|
||||||
|
|
||||||
goto freeze;
|
goto freeze;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (unlikely(!qc))
|
if (!(bmdma2 & SIL_DMA_COMPLETE))
|
||||||
goto freeze;
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (unlikely(qc->tf.flags & ATA_TFLAG_POLLING)) {
|
if (unlikely(!qc || (qc->tf.flags & ATA_TFLAG_POLLING))) {
|
||||||
/* this sometimes happens, just clear IRQ */
|
/* this sometimes happens, just clear IRQ */
|
||||||
ata_chk_status(ap);
|
ata_chk_status(ap);
|
||||||
return;
|
return;
|
||||||
|
|
Reference in New Issue