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>
This commit is contained in:
parent
7f25377043
commit
836250069f
@ -2664,8 +2664,7 @@ void ata_bus_reset(struct ata_port *ap)
|
|||||||
ap->device[1].class = ata_dev_try_classify(ap, 1, &err);
|
ap->device[1].class = ata_dev_try_classify(ap, 1, &err);
|
||||||
|
|
||||||
/* re-enable interrupts */
|
/* re-enable interrupts */
|
||||||
if (ap->ioaddr.ctl_addr) /* FIXME: hack. create a hook instead */
|
ap->ops->irq_on(ap);
|
||||||
ata_irq_on(ap);
|
|
||||||
|
|
||||||
/* is double-select really necessary? */
|
/* is double-select really necessary? */
|
||||||
if (ap->device[1].class != ATA_DEV_NONE)
|
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);
|
sata_scr_write(ap, SCR_ERROR, serror);
|
||||||
|
|
||||||
/* re-enable interrupts */
|
/* re-enable interrupts */
|
||||||
if (!ap->ops->error_handler) {
|
if (!ap->ops->error_handler)
|
||||||
/* FIXME: hack. create a hook instead */
|
ap->ops->irq_on(ap);
|
||||||
if (ap->ioaddr.ctl_addr)
|
|
||||||
ata_irq_on(ap);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* is double-select really necessary? */
|
/* is double-select really necessary? */
|
||||||
if (classes[0] != ATA_DEV_NONE)
|
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);
|
qc = ata_qc_from_tag(ap, qc->tag);
|
||||||
if (qc) {
|
if (qc) {
|
||||||
if (likely(!(qc->err_mask & AC_ERR_HSM))) {
|
if (likely(!(qc->err_mask & AC_ERR_HSM))) {
|
||||||
ata_irq_on(ap);
|
ap->ops->irq_on(ap);
|
||||||
ata_qc_complete(qc);
|
ata_qc_complete(qc);
|
||||||
} else
|
} else
|
||||||
ata_port_freeze(ap);
|
ata_port_freeze(ap);
|
||||||
@ -4185,7 +4181,7 @@ static void ata_hsm_qc_complete(struct ata_queued_cmd *qc, int in_wq)
|
|||||||
} else {
|
} else {
|
||||||
if (in_wq) {
|
if (in_wq) {
|
||||||
spin_lock_irqsave(ap->lock, flags);
|
spin_lock_irqsave(ap->lock, flags);
|
||||||
ata_irq_on(ap);
|
ap->ops->irq_on(ap);
|
||||||
ata_qc_complete(qc);
|
ata_qc_complete(qc);
|
||||||
spin_unlock_irqrestore(ap->lock, flags);
|
spin_unlock_irqrestore(ap->lock, flags);
|
||||||
} else
|
} else
|
||||||
@ -5010,7 +5006,7 @@ inline unsigned int ata_host_intr (struct ata_port *ap,
|
|||||||
|
|
||||||
#ifdef ATA_IRQ_TRAP
|
#ifdef ATA_IRQ_TRAP
|
||||||
if ((ap->stats.idle_irq % 1000) == 0) {
|
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");
|
ata_port_printk(ap, KERN_WARNING, "irq trap\n");
|
||||||
return 1;
|
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_complete);
|
||||||
EXPORT_SYMBOL_GPL(ata_eh_qc_retry);
|
EXPORT_SYMBOL_GPL(ata_eh_qc_retry);
|
||||||
EXPORT_SYMBOL_GPL(ata_do_eh);
|
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);
|
||||||
|
@ -64,6 +64,46 @@ u8 ata_irq_on(struct ata_port *ap)
|
|||||||
return tmp;
|
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
|
* ata_tf_load - send taskfile registers to host controller
|
||||||
* @ap: Port to which output is sent
|
* @ap: Port to which output is sent
|
||||||
@ -370,8 +410,7 @@ void ata_bmdma_thaw(struct ata_port *ap)
|
|||||||
/* clear & re-enable interrupts */
|
/* clear & re-enable interrupts */
|
||||||
ata_chk_status(ap);
|
ata_chk_status(ap);
|
||||||
ap->ops->irq_clear(ap);
|
ap->ops->irq_clear(ap);
|
||||||
if (ap->ioaddr.ctl_addr) /* FIXME: hack. create a hook instead */
|
ap->ops->irq_on(ap);
|
||||||
ata_irq_on(ap);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -632,6 +632,8 @@ struct ata_port_operations {
|
|||||||
|
|
||||||
irq_handler_t irq_handler;
|
irq_handler_t irq_handler;
|
||||||
void (*irq_clear) (struct ata_port *);
|
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);
|
u32 (*scr_read) (struct ata_port *ap, unsigned int sc_reg);
|
||||||
void (*scr_write) (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,
|
extern int ata_scsi_change_queue_depth(struct scsi_device *sdev,
|
||||||
int queue_depth);
|
int queue_depth);
|
||||||
extern struct ata_device *ata_dev_pair(struct ata_device *adev);
|
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
|
* Timing helpers
|
||||||
@ -1147,42 +1153,6 @@ static inline void ata_qc_reinit(struct ata_queued_cmd *qc)
|
|||||||
qc->result_tf.feature = 0;
|
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)
|
static inline int ata_try_flush_cache(const struct ata_device *dev)
|
||||||
{
|
{
|
||||||
return ata_id_wcache_enabled(dev->id) ||
|
return ata_id_wcache_enabled(dev->id) ||
|
||||||
|
Loading…
Reference in New Issue
Block a user