aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/ata
diff options
context:
space:
mode:
authorTejun Heo <htejun@gmail.com>2006-11-16 22:24:22 -0500
committerTejun Heo <htejun@gmail.com>2006-12-03 03:56:24 -0500
commit0f0a3ad3741fd93461fcfb85dc577103c58d9be8 (patch)
tree1d91117b58b6c3878f6b346e8e8f4c7b93dbca9f /drivers/ata
parentea54763f8a7c51b9f8fcb14431812ae63fcbaf96 (diff)
[PATCH] libata: make sure IRQ is cleared after ata_bmdma_freeze()
Now that BMDMA status is recorded in irq handler. ata_bmdma_freeze() is free to manipulate host status. Under certain circumstances, some controllers (ICH7 in enhanced mode w/ IRQ shared) raise IRQ when CTL register is written to and ATA_NIEN doesn't mask it. This patch makes ata_bmdma_freeze() clear all pending IRQs after freezing a port. This change makes explicit clearing in ata_device_add() unnecessary and thus kills it. The removed code was SFF-specific and was in the wrong place. Note that ->freeze() handler is always called under ap->lock held and irq disabled. Even if CTL manipulation causes stuck IRQ, it's cleared immediately. This should be safe (enough) even in SMP environment. More correct solution is to mask the IRQ from IRQ controller but that would be an overkill. Signed-off-by: Tejun Heo <htejun@gmail.com>
Diffstat (limited to 'drivers/ata')
-rw-r--r--drivers/ata/libata-core.c5
-rw-r--r--drivers/ata/libata-sff.c8
2 files changed, 10 insertions, 3 deletions
diff --git a/drivers/ata/libata-core.c b/drivers/ata/libata-core.c
index 7f53ea725bce..47c70392ec4d 100644
--- a/drivers/ata/libata-core.c
+++ b/drivers/ata/libata-core.c
@@ -5681,9 +5681,8 @@ int ata_device_add(const struct ata_probe_ent *ent)
5681 ap->ioaddr.bmdma_addr, 5681 ap->ioaddr.bmdma_addr,
5682 irq_line); 5682 irq_line);
5683 5683
5684 ata_chk_status(ap); 5684 /* freeze port before requesting IRQ */
5685 host->ops->irq_clear(ap); 5685 ata_eh_freeze_port(ap);
5686 ata_eh_freeze_port(ap); /* freeze port before requesting IRQ */
5687 } 5686 }
5688 5687
5689 /* obtain irq, that may be shared between channels */ 5688 /* obtain irq, that may be shared between channels */
diff --git a/drivers/ata/libata-sff.c b/drivers/ata/libata-sff.c
index 95ff186f0ccd..10ee22ae5c15 100644
--- a/drivers/ata/libata-sff.c
+++ b/drivers/ata/libata-sff.c
@@ -700,6 +700,14 @@ void ata_bmdma_freeze(struct ata_port *ap)
700 writeb(ap->ctl, (void __iomem *)ioaddr->ctl_addr); 700 writeb(ap->ctl, (void __iomem *)ioaddr->ctl_addr);
701 else 701 else
702 outb(ap->ctl, ioaddr->ctl_addr); 702 outb(ap->ctl, ioaddr->ctl_addr);
703
704 /* Under certain circumstances, some controllers raise IRQ on
705 * ATA_NIEN manipulation. Also, many controllers fail to mask
706 * previously pending IRQ on ATA_NIEN assertion. Clear it.
707 */
708 ata_chk_status(ap);
709
710 ap->ops->irq_clear(ap);
703} 711}
704 712
705/** 713/**