From 836250069fc0eeebe8b6aed772281535cc6e34f9 Mon Sep 17 00:00:00 2001 From: Akira Iguchi Date: Fri, 26 Jan 2007 16:27:32 +0900 Subject: [PATCH] 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 +++++++++++++++++++++++++++++++++++++-- include/linux/libata.h | 42 ++++++-------------------------------- 3 files changed, 57 insertions(+), 48 deletions(-) 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); } /** diff --git a/include/linux/libata.h b/include/linux/libata.h index 308bb8cbe50..bdfe6ea8edf 100644 --- a/include/linux/libata.h +++ b/include/linux/libata.h @@ -632,6 +632,8 @@ struct ata_port_operations { irq_handler_t irq_handler; void (*irq_clear) (struct ata_port *); + u8 (*irq_on) (struct ata_port *); + u8 (*irq_ack) (struct ata_port *ap, unsigned int chk_drq); u32 (*scr_read) (struct ata_port *ap, unsigned int sc_reg); void (*scr_write) (struct ata_port *ap, unsigned int sc_reg, @@ -813,6 +815,10 @@ extern void ata_scsi_slave_destroy(struct scsi_device *sdev); extern int ata_scsi_change_queue_depth(struct scsi_device *sdev, int queue_depth); extern struct ata_device *ata_dev_pair(struct ata_device *adev); +extern u8 ata_irq_on(struct ata_port *ap); +extern u8 ata_dummy_irq_on(struct ata_port *ap); +extern u8 ata_irq_ack(struct ata_port *ap, unsigned int chk_drq); +extern u8 ata_dummy_irq_ack(struct ata_port *ap, unsigned int chk_drq); /* * Timing helpers @@ -1147,42 +1153,6 @@ static inline void ata_qc_reinit(struct ata_queued_cmd *qc) qc->result_tf.feature = 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: - */ - -static inline 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; -} - static inline int ata_try_flush_cache(const struct ata_device *dev) { return ata_id_wcache_enabled(dev->id) || -- 2.41.1