diff options
author | Akira Iguchi <akira2.iguchi@toshiba.co.jp> | 2007-01-26 02:27:32 -0500 |
---|---|---|
committer | Jeff Garzik <jeff@garzik.org> | 2007-02-09 17:39:38 -0500 |
commit | 836250069fc0eeebe8b6aed772281535cc6e34f9 (patch) | |
tree | 73c886ae7fd75dd2c9b5b17e11ea3b6b76b42fed | |
parent | 7f25377043925554cb9f3f9d8ada3390f71a5d10 (diff) |
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 <kou.ishizaki@toshiba.co.jp>
Signed-off-by: Akira Iguchi <akira2.iguchi@toshiba.co.jp>
Signed-off-by: Jeff Garzik <jeff@garzik.org>
-rw-r--r-- | drivers/ata/libata-core.c | 20 | ||||
-rw-r--r-- | drivers/ata/libata-sff.c | 43 | ||||
-rw-r--r-- | 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 f210dbd4cbe6..2e8ca652c0d9 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) | |||
2664 | ap->device[1].class = ata_dev_try_classify(ap, 1, &err); | 2664 | ap->device[1].class = ata_dev_try_classify(ap, 1, &err); |
2665 | 2665 | ||
2666 | /* re-enable interrupts */ | 2666 | /* re-enable interrupts */ |
2667 | if (ap->ioaddr.ctl_addr) /* FIXME: hack. create a hook instead */ | 2667 | ap->ops->irq_on(ap); |
2668 | ata_irq_on(ap); | ||
2669 | 2668 | ||
2670 | /* is double-select really necessary? */ | 2669 | /* is double-select really necessary? */ |
2671 | if (ap->device[1].class != ATA_DEV_NONE) | 2670 | if (ap->device[1].class != ATA_DEV_NONE) |
@@ -3054,11 +3053,8 @@ void ata_std_postreset(struct ata_port *ap, unsigned int *classes) | |||
3054 | sata_scr_write(ap, SCR_ERROR, serror); | 3053 | sata_scr_write(ap, SCR_ERROR, serror); |
3055 | 3054 | ||
3056 | /* re-enable interrupts */ | 3055 | /* re-enable interrupts */ |
3057 | if (!ap->ops->error_handler) { | 3056 | if (!ap->ops->error_handler) |
3058 | /* FIXME: hack. create a hook instead */ | 3057 | ap->ops->irq_on(ap); |
3059 | if (ap->ioaddr.ctl_addr) | ||
3060 | ata_irq_on(ap); | ||
3061 | } | ||
3062 | 3058 | ||
3063 | /* is double-select really necessary? */ | 3059 | /* is double-select really necessary? */ |
3064 | if (classes[0] != ATA_DEV_NONE) | 3060 | if (classes[0] != ATA_DEV_NONE) |
@@ -4169,7 +4165,7 @@ static void ata_hsm_qc_complete(struct ata_queued_cmd *qc, int in_wq) | |||
4169 | qc = ata_qc_from_tag(ap, qc->tag); | 4165 | qc = ata_qc_from_tag(ap, qc->tag); |
4170 | if (qc) { | 4166 | if (qc) { |
4171 | if (likely(!(qc->err_mask & AC_ERR_HSM))) { | 4167 | if (likely(!(qc->err_mask & AC_ERR_HSM))) { |
4172 | ata_irq_on(ap); | 4168 | ap->ops->irq_on(ap); |
4173 | ata_qc_complete(qc); | 4169 | ata_qc_complete(qc); |
4174 | } else | 4170 | } else |
4175 | ata_port_freeze(ap); | 4171 | ata_port_freeze(ap); |
@@ -4185,7 +4181,7 @@ static void ata_hsm_qc_complete(struct ata_queued_cmd *qc, int in_wq) | |||
4185 | } else { | 4181 | } else { |
4186 | if (in_wq) { | 4182 | if (in_wq) { |
4187 | spin_lock_irqsave(ap->lock, flags); | 4183 | spin_lock_irqsave(ap->lock, flags); |
4188 | ata_irq_on(ap); | 4184 | ap->ops->irq_on(ap); |
4189 | ata_qc_complete(qc); | 4185 | ata_qc_complete(qc); |
4190 | spin_unlock_irqrestore(ap->lock, flags); | 4186 | spin_unlock_irqrestore(ap->lock, flags); |
4191 | } else | 4187 | } else |
@@ -5010,7 +5006,7 @@ idle_irq: | |||
5010 | 5006 | ||
5011 | #ifdef ATA_IRQ_TRAP | 5007 | #ifdef ATA_IRQ_TRAP |
5012 | if ((ap->stats.idle_irq % 1000) == 0) { | 5008 | if ((ap->stats.idle_irq % 1000) == 0) { |
5013 | ata_irq_ack(ap, 0); /* debug trap */ | 5009 | ap->ops->irq_ack(ap, 0); /* debug trap */ |
5014 | ata_port_printk(ap, KERN_WARNING, "irq trap\n"); | 5010 | ata_port_printk(ap, KERN_WARNING, "irq trap\n"); |
5015 | return 1; | 5011 | return 1; |
5016 | } | 5012 | } |
@@ -6271,3 +6267,7 @@ EXPORT_SYMBOL_GPL(ata_eh_thaw_port); | |||
6271 | EXPORT_SYMBOL_GPL(ata_eh_qc_complete); | 6267 | EXPORT_SYMBOL_GPL(ata_eh_qc_complete); |
6272 | EXPORT_SYMBOL_GPL(ata_eh_qc_retry); | 6268 | EXPORT_SYMBOL_GPL(ata_eh_qc_retry); |
6273 | EXPORT_SYMBOL_GPL(ata_do_eh); | 6269 | EXPORT_SYMBOL_GPL(ata_do_eh); |
6270 | EXPORT_SYMBOL_GPL(ata_irq_on); | ||
6271 | EXPORT_SYMBOL_GPL(ata_dummy_irq_on); | ||
6272 | EXPORT_SYMBOL_GPL(ata_irq_ack); | ||
6273 | EXPORT_SYMBOL_GPL(ata_dummy_irq_ack); | ||
diff --git a/drivers/ata/libata-sff.c b/drivers/ata/libata-sff.c index c561b3be4a97..16bc3e35bdd4 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) | |||
64 | return tmp; | 64 | return tmp; |
65 | } | 65 | } |
66 | 66 | ||
67 | u8 ata_dummy_irq_on (struct ata_port *ap) { return 0; } | ||
68 | |||
69 | /** | ||
70 | * ata_irq_ack - Acknowledge a device interrupt. | ||
71 | * @ap: Port on which interrupts are enabled. | ||
72 | * | ||
73 | * Wait up to 10 ms for legacy IDE device to become idle (BUSY | ||
74 | * or BUSY+DRQ clear). Obtain dma status and port status from | ||
75 | * device. Clear the interrupt. Return port status. | ||
76 | * | ||
77 | * LOCKING: | ||
78 | */ | ||
79 | |||
80 | u8 ata_irq_ack(struct ata_port *ap, unsigned int chk_drq) | ||
81 | { | ||
82 | unsigned int bits = chk_drq ? ATA_BUSY | ATA_DRQ : ATA_BUSY; | ||
83 | u8 host_stat, post_stat, status; | ||
84 | |||
85 | status = ata_busy_wait(ap, bits, 1000); | ||
86 | if (status & bits) | ||
87 | if (ata_msg_err(ap)) | ||
88 | printk(KERN_ERR "abnormal status 0x%X\n", status); | ||
89 | |||
90 | /* get controller status; clear intr, err bits */ | ||
91 | host_stat = ioread8(ap->ioaddr.bmdma_addr + ATA_DMA_STATUS); | ||
92 | iowrite8(host_stat | ATA_DMA_INTR | ATA_DMA_ERR, | ||
93 | ap->ioaddr.bmdma_addr + ATA_DMA_STATUS); | ||
94 | |||
95 | post_stat = ioread8(ap->ioaddr.bmdma_addr + ATA_DMA_STATUS); | ||
96 | |||
97 | if (ata_msg_intr(ap)) | ||
98 | printk(KERN_INFO "%s: irq ack: host_stat 0x%X, new host_stat 0x%X, drv_stat 0x%X\n", | ||
99 | __FUNCTION__, | ||
100 | host_stat, post_stat, status); | ||
101 | |||
102 | return status; | ||
103 | } | ||
104 | |||
105 | u8 ata_dummy_irq_ack(struct ata_port *ap, unsigned int chk_drq) { return 0; } | ||
106 | |||
67 | /** | 107 | /** |
68 | * ata_tf_load - send taskfile registers to host controller | 108 | * ata_tf_load - send taskfile registers to host controller |
69 | * @ap: Port to which output is sent | 109 | * @ap: Port to which output is sent |
@@ -370,8 +410,7 @@ void ata_bmdma_thaw(struct ata_port *ap) | |||
370 | /* clear & re-enable interrupts */ | 410 | /* clear & re-enable interrupts */ |
371 | ata_chk_status(ap); | 411 | ata_chk_status(ap); |
372 | ap->ops->irq_clear(ap); | 412 | ap->ops->irq_clear(ap); |
373 | if (ap->ioaddr.ctl_addr) /* FIXME: hack. create a hook instead */ | 413 | ap->ops->irq_on(ap); |
374 | ata_irq_on(ap); | ||
375 | } | 414 | } |
376 | 415 | ||
377 | /** | 416 | /** |
diff --git a/include/linux/libata.h b/include/linux/libata.h index 308bb8cbe50f..bdfe6ea8edf7 100644 --- a/include/linux/libata.h +++ b/include/linux/libata.h | |||
@@ -632,6 +632,8 @@ struct ata_port_operations { | |||
632 | 632 | ||
633 | irq_handler_t irq_handler; | 633 | irq_handler_t irq_handler; |
634 | void (*irq_clear) (struct ata_port *); | 634 | void (*irq_clear) (struct ata_port *); |
635 | u8 (*irq_on) (struct ata_port *); | ||
636 | u8 (*irq_ack) (struct ata_port *ap, unsigned int chk_drq); | ||
635 | 637 | ||
636 | u32 (*scr_read) (struct ata_port *ap, unsigned int sc_reg); | 638 | u32 (*scr_read) (struct ata_port *ap, unsigned int sc_reg); |
637 | void (*scr_write) (struct ata_port *ap, unsigned int sc_reg, | 639 | 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); | |||
813 | extern int ata_scsi_change_queue_depth(struct scsi_device *sdev, | 815 | extern int ata_scsi_change_queue_depth(struct scsi_device *sdev, |
814 | int queue_depth); | 816 | int queue_depth); |
815 | extern struct ata_device *ata_dev_pair(struct ata_device *adev); | 817 | extern struct ata_device *ata_dev_pair(struct ata_device *adev); |
818 | extern u8 ata_irq_on(struct ata_port *ap); | ||
819 | extern u8 ata_dummy_irq_on(struct ata_port *ap); | ||
820 | extern u8 ata_irq_ack(struct ata_port *ap, unsigned int chk_drq); | ||
821 | extern u8 ata_dummy_irq_ack(struct ata_port *ap, unsigned int chk_drq); | ||
816 | 822 | ||
817 | /* | 823 | /* |
818 | * Timing helpers | 824 | * Timing helpers |
@@ -1147,42 +1153,6 @@ static inline void ata_qc_reinit(struct ata_queued_cmd *qc) | |||
1147 | qc->result_tf.feature = 0; | 1153 | qc->result_tf.feature = 0; |
1148 | } | 1154 | } |
1149 | 1155 | ||
1150 | /** | ||
1151 | * ata_irq_ack - Acknowledge a device interrupt. | ||
1152 | * @ap: Port on which interrupts are enabled. | ||
1153 | * | ||
1154 | * Wait up to 10 ms for legacy IDE device to become idle (BUSY | ||
1155 | * or BUSY+DRQ clear). Obtain dma status and port status from | ||
1156 | * device. Clear the interrupt. Return port status. | ||
1157 | * | ||
1158 | * LOCKING: | ||
1159 | */ | ||
1160 | |||
1161 | static inline u8 ata_irq_ack(struct ata_port *ap, unsigned int chk_drq) | ||
1162 | { | ||
1163 | unsigned int bits = chk_drq ? ATA_BUSY | ATA_DRQ : ATA_BUSY; | ||
1164 | u8 host_stat, post_stat, status; | ||
1165 | |||
1166 | status = ata_busy_wait(ap, bits, 1000); | ||
1167 | if (status & bits) | ||
1168 | if (ata_msg_err(ap)) | ||
1169 | printk(KERN_ERR "abnormal status 0x%X\n", status); | ||
1170 | |||
1171 | /* get controller status; clear intr, err bits */ | ||
1172 | host_stat = ioread8(ap->ioaddr.bmdma_addr + ATA_DMA_STATUS); | ||
1173 | iowrite8(host_stat | ATA_DMA_INTR | ATA_DMA_ERR, | ||
1174 | ap->ioaddr.bmdma_addr + ATA_DMA_STATUS); | ||
1175 | |||
1176 | post_stat = ioread8(ap->ioaddr.bmdma_addr + ATA_DMA_STATUS); | ||
1177 | |||
1178 | if (ata_msg_intr(ap)) | ||
1179 | printk(KERN_INFO "%s: irq ack: host_stat 0x%X, new host_stat 0x%X, drv_stat 0x%X\n", | ||
1180 | __FUNCTION__, | ||
1181 | host_stat, post_stat, status); | ||
1182 | |||
1183 | return status; | ||
1184 | } | ||
1185 | |||
1186 | static inline int ata_try_flush_cache(const struct ata_device *dev) | 1156 | static inline int ata_try_flush_cache(const struct ata_device *dev) |
1187 | { | 1157 | { |
1188 | return ata_id_wcache_enabled(dev->id) || | 1158 | return ata_id_wcache_enabled(dev->id) || |