From 836250069fc0eeebe8b6aed772281535cc6e34f9 Mon Sep 17 00:00:00 2001 From: Akira Iguchi Date: Fri, 26 Jan 2007 16:27:32 +0900 Subject: libata: add another IRQ calls (core and headers) This patch is against the libata core and headers. Two IRQ calls are added in ata_port_operations. - irq_on() is used to enable interrupts. - irq_ack() is used to acknowledge a device interrupt. In most drivers, ata_irq_on() and ata_irq_ack() are used for irq_on and irq_ack respectively. In some drivers (ex: ahci, sata_sil24) which cannot use them as is, ata_dummy_irq_on() and ata_dummy_irq_ack() are used. Signed-off-by: Kou Ishizaki Signed-off-by: Akira Iguchi Signed-off-by: Jeff Garzik --- drivers/ata/libata-core.c | 20 ++++++++++---------- drivers/ata/libata-sff.c | 43 +++++++++++++++++++++++++++++++++++++++++-- 2 files changed, 51 insertions(+), 12 deletions(-) (limited to 'drivers') diff --git a/drivers/ata/libata-core.c b/drivers/ata/libata-core.c index f210dbd4cbe..2e8ca652c0d 100644 --- a/drivers/ata/libata-core.c +++ b/drivers/ata/libata-core.c @@ -2664,8 +2664,7 @@ void ata_bus_reset(struct ata_port *ap) ap->device[1].class = ata_dev_try_classify(ap, 1, &err); /* re-enable interrupts */ - if (ap->ioaddr.ctl_addr) /* FIXME: hack. create a hook instead */ - ata_irq_on(ap); + ap->ops->irq_on(ap); /* is double-select really necessary? */ if (ap->device[1].class != ATA_DEV_NONE) @@ -3054,11 +3053,8 @@ void ata_std_postreset(struct ata_port *ap, unsigned int *classes) sata_scr_write(ap, SCR_ERROR, serror); /* re-enable interrupts */ - if (!ap->ops->error_handler) { - /* FIXME: hack. create a hook instead */ - if (ap->ioaddr.ctl_addr) - ata_irq_on(ap); - } + if (!ap->ops->error_handler) + ap->ops->irq_on(ap); /* is double-select really necessary? */ if (classes[0] != ATA_DEV_NONE) @@ -4169,7 +4165,7 @@ static void ata_hsm_qc_complete(struct ata_queued_cmd *qc, int in_wq) qc = ata_qc_from_tag(ap, qc->tag); if (qc) { if (likely(!(qc->err_mask & AC_ERR_HSM))) { - ata_irq_on(ap); + ap->ops->irq_on(ap); ata_qc_complete(qc); } else ata_port_freeze(ap); @@ -4185,7 +4181,7 @@ static void ata_hsm_qc_complete(struct ata_queued_cmd *qc, int in_wq) } else { if (in_wq) { spin_lock_irqsave(ap->lock, flags); - ata_irq_on(ap); + ap->ops->irq_on(ap); ata_qc_complete(qc); spin_unlock_irqrestore(ap->lock, flags); } else @@ -5010,7 +5006,7 @@ idle_irq: #ifdef ATA_IRQ_TRAP if ((ap->stats.idle_irq % 1000) == 0) { - ata_irq_ack(ap, 0); /* debug trap */ + ap->ops->irq_ack(ap, 0); /* debug trap */ ata_port_printk(ap, KERN_WARNING, "irq trap\n"); return 1; } @@ -6271,3 +6267,7 @@ EXPORT_SYMBOL_GPL(ata_eh_thaw_port); EXPORT_SYMBOL_GPL(ata_eh_qc_complete); EXPORT_SYMBOL_GPL(ata_eh_qc_retry); EXPORT_SYMBOL_GPL(ata_do_eh); +EXPORT_SYMBOL_GPL(ata_irq_on); +EXPORT_SYMBOL_GPL(ata_dummy_irq_on); +EXPORT_SYMBOL_GPL(ata_irq_ack); +EXPORT_SYMBOL_GPL(ata_dummy_irq_ack); diff --git a/drivers/ata/libata-sff.c b/drivers/ata/libata-sff.c index c561b3be4a9..16bc3e35bdd 100644 --- a/drivers/ata/libata-sff.c +++ b/drivers/ata/libata-sff.c @@ -64,6 +64,46 @@ u8 ata_irq_on(struct ata_port *ap) return tmp; } +u8 ata_dummy_irq_on (struct ata_port *ap) { return 0; } + +/** + * ata_irq_ack - Acknowledge a device interrupt. + * @ap: Port on which interrupts are enabled. + * + * Wait up to 10 ms for legacy IDE device to become idle (BUSY + * or BUSY+DRQ clear). Obtain dma status and port status from + * device. Clear the interrupt. Return port status. + * + * LOCKING: + */ + +u8 ata_irq_ack(struct ata_port *ap, unsigned int chk_drq) +{ + unsigned int bits = chk_drq ? ATA_BUSY | ATA_DRQ : ATA_BUSY; + u8 host_stat, post_stat, status; + + status = ata_busy_wait(ap, bits, 1000); + if (status & bits) + if (ata_msg_err(ap)) + printk(KERN_ERR "abnormal status 0x%X\n", status); + + /* get controller status; clear intr, err bits */ + host_stat = ioread8(ap->ioaddr.bmdma_addr + ATA_DMA_STATUS); + iowrite8(host_stat | ATA_DMA_INTR | ATA_DMA_ERR, + ap->ioaddr.bmdma_addr + ATA_DMA_STATUS); + + post_stat = ioread8(ap->ioaddr.bmdma_addr + ATA_DMA_STATUS); + + if (ata_msg_intr(ap)) + printk(KERN_INFO "%s: irq ack: host_stat 0x%X, new host_stat 0x%X, drv_stat 0x%X\n", + __FUNCTION__, + host_stat, post_stat, status); + + return status; +} + +u8 ata_dummy_irq_ack(struct ata_port *ap, unsigned int chk_drq) { return 0; } + /** * ata_tf_load - send taskfile registers to host controller * @ap: Port to which output is sent @@ -370,8 +410,7 @@ void ata_bmdma_thaw(struct ata_port *ap) /* clear & re-enable interrupts */ ata_chk_status(ap); ap->ops->irq_clear(ap); - if (ap->ioaddr.ctl_addr) /* FIXME: hack. create a hook instead */ - ata_irq_on(ap); + ap->ops->irq_on(ap); } /** -- cgit v1.2.3