Skip to content

Commit

Permalink
libata: add another IRQ calls (core and headers)
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
Akira Iguchi authored and Jeff Garzik committed Feb 9, 2007
1 parent 7f25377 commit 8362500
Show file tree
Hide file tree
Showing 3 changed files with 57 additions and 48 deletions.
20 changes: 10 additions & 10 deletions drivers/ata/libata-core.c
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down Expand Up @@ -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)
Expand Down Expand Up @@ -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);
Expand All @@ -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
Expand Down Expand Up @@ -5010,7 +5006,7 @@ inline unsigned int ata_host_intr (struct ata_port *ap,

#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;
}
Expand Down Expand Up @@ -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);
43 changes: 41 additions & 2 deletions drivers/ata/libata-sff.c
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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);
}

/**
Expand Down
42 changes: 6 additions & 36 deletions include/linux/libata.h
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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) ||
Expand Down

0 comments on commit 8362500

Please sign in to comment.