summaryrefslogtreecommitdiff
path: root/include/linux/libata.h
diff options
context:
space:
mode:
authorJeff Garzik <jgarzik@pobox.com>2004-07-03 14:40:48 -0400
committerJeff Garzik <jgarzik@pobox.com>2004-07-03 14:40:48 -0400
commitea21e4ac2f5d655db154b64329c437688c92f7d5 (patch)
treea0e598bc5b94d821e06f359474ea55414ccb4da7 /include/linux/libata.h
parente69207190a6f3c9d0413c4a8c9518dd07d18e0a3 (diff)
[libata] create, and use, ->irq_clear hook
This is more conservative in general, and so applies to multiple controllers. Specifically it attempts to address irq-related issues on the Intel ICH5/6 hardware. On Intel ICH5/6, the BMDMA 'interrupt' status bit will be set even on non-DMA commands, which software (and I) did not expect. This change clears pending interrupts once upon initialization, and then each time ata_irq_on() is called.
Diffstat (limited to 'include/linux/libata.h')
-rw-r--r--include/linux/libata.h10
1 files changed, 9 insertions, 1 deletions
diff --git a/include/linux/libata.h b/include/linux/libata.h
index c57be1ab010d..7fc0c2763f88 100644
--- a/include/linux/libata.h
+++ b/include/linux/libata.h
@@ -202,6 +202,7 @@ struct ata_host_set {
void *mmio_base;
unsigned int n_ports;
void *private_data;
+ struct ata_port_operations *ops;
struct ata_port * ports[0];
};
@@ -318,6 +319,7 @@ struct ata_port_operations {
void (*eng_timeout) (struct ata_port *ap);
irqreturn_t (*irq_handler)(int, void *, struct pt_regs *);
+ void (*irq_clear) (struct ata_port *);
u32 (*scr_read) (struct ata_port *ap, unsigned int sc_reg);
void (*scr_write) (struct ata_port *ap, unsigned int sc_reg,
@@ -382,6 +384,7 @@ extern void ata_bmdma_setup_mmio (struct ata_queued_cmd *qc);
extern void ata_bmdma_start_mmio (struct ata_queued_cmd *qc);
extern void ata_bmdma_setup_pio (struct ata_queued_cmd *qc);
extern void ata_bmdma_start_pio (struct ata_queued_cmd *qc);
+extern void ata_bmdma_irq_clear(struct ata_port *ap);
extern int pci_test_config_bits(struct pci_dev *pdev, struct pci_bits *bits);
extern void ata_qc_complete(struct ata_queued_cmd *qc, u8 drv_stat);
extern void ata_eng_timeout(struct ata_port *ap);
@@ -484,6 +487,7 @@ static inline void ata_tf_init(struct ata_port *ap, struct ata_taskfile *tf, uns
static inline u8 ata_irq_on(struct ata_port *ap)
{
struct ata_ioports *ioaddr = &ap->ioaddr;
+ u8 tmp;
ap->ctl &= ~ATA_NIEN;
ap->last_ctl = ap->ctl;
@@ -492,7 +496,11 @@ static inline u8 ata_irq_on(struct ata_port *ap)
writeb(ap->ctl, ioaddr->ctl_addr);
else
outb(ap->ctl, ioaddr->ctl_addr);
- return ata_wait_idle(ap);
+ tmp = ata_wait_idle(ap);
+
+ ap->ops->irq_clear(ap);
+
+ return tmp;
}
static inline u8 ata_irq_ack(struct ata_port *ap, unsigned int chk_drq)