aboutsummaryrefslogtreecommitdiff
path: root/drivers/scsi
diff options
context:
space:
mode:
authorTejun Heo <htejun@gmail.com>2006-06-12 18:45:55 +0900
committerJeff Garzik <jeff@garzik.org>2006-06-12 09:37:21 -0400
commitd4c85325a817d3351e61c4be64b437116e8483b4 (patch)
tree6a97a2e92a3068782cca7d139456e695c82935ec /drivers/scsi
parentaeb2ecd6096182cc080d37679080c0f088dcd4a4 (diff)
[PATCH] sata_sil: update device hotplug handling, take #2
SIEN on some 3112 controllers doesn't mask SATA IRQ properly. IRQ stays asserted even after SIEN is masked and IRQ is acked. Also, even while frozen, any SATA PHY event including hardreset raises SATA IRQ. Clearing SError seems to be the only way to deassert SATA IRQ. This patch makes sil_host_intr() clear SError on SATA IRQs and ignore SATA IRQs reported while frozen so that hardreset doesn't trigger hotplug event (which ends up hardresetting again). In such cases, the port still gets re-frozen to minimize the danger of screaming interrupts. This results in one nil EH repeat on controllers with broken SIEN but other than that does no harm. Signed-off-by: Tejun Heo <htejun@gmail.com> Signed-off-by: Jeff Garzik <jeff@garzik.org>
Diffstat (limited to 'drivers/scsi')
-rw-r--r--drivers/scsi/sata_sil.c20
1 files changed, 19 insertions, 1 deletions
diff --git a/drivers/scsi/sata_sil.c b/drivers/scsi/sata_sil.c
index a7e99a1def2..bc9f918a7f2 100644
--- a/drivers/scsi/sata_sil.c
+++ b/drivers/scsi/sata_sil.c
@@ -344,7 +344,25 @@ static void sil_host_intr(struct ata_port *ap, u32 bmdma2)
u8 status;
if (unlikely(bmdma2 & SIL_DMA_SATA_IRQ)) {
- ata_ehi_hotplugged(&ap->eh_info);
+ u32 serror;
+
+ /* SIEN doesn't mask SATA IRQs on some 3112s. Those
+ * controllers continue to assert IRQ as long as
+ * SError bits are pending. Clear SError immediately.
+ */
+ serror = sil_scr_read(ap, SCR_ERROR);
+ sil_scr_write(ap, SCR_ERROR, serror);
+
+ /* 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->flags & ATA_FLAG_FROZEN)) {
+ ata_ehi_hotplugged(&ap->eh_info);
+ ap->eh_info.serror |= serror;
+ }
+
goto freeze;
}