Patch 2/10: Currently there is ->irq_on but no ->irq_off. Turning irq off is done via altering the nIEN bit of qc->tf, together with tf_load(). This patch adds ->irq_off for symmetry. tf_load() and ata_qc_set_polling() will be fixed/removed in later patches. Signed-off-by: Albert Lee <albertcc@xxxxxxxxxx> --- diff -Nrup 01_remove_leftover_irqon/drivers/ata/libata-core.c 02_add_irq_off/drivers/ata/libata-core.c --- 01_remove_leftover_irqon/drivers/ata/libata-core.c 2007-07-04 11:43:30.000000000 +0800 +++ 02_add_irq_off/drivers/ata/libata-core.c 2007-07-04 11:57:33.000000000 +0800 @@ -6901,6 +6901,8 @@ 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_off); +EXPORT_SYMBOL_GPL(ata_dummy_irq_off); EXPORT_SYMBOL_GPL(ata_irq_ack); EXPORT_SYMBOL_GPL(ata_dummy_irq_ack); EXPORT_SYMBOL_GPL(ata_dev_try_classify); diff -Nrup 01_remove_leftover_irqon/drivers/ata/libata-sff.c 02_add_irq_off/drivers/ata/libata-sff.c --- 01_remove_leftover_irqon/drivers/ata/libata-sff.c 2007-07-04 11:26:30.000000000 +0800 +++ 02_add_irq_off/drivers/ata/libata-sff.c 2007-07-04 11:57:33.000000000 +0800 @@ -67,6 +67,39 @@ u8 ata_irq_on(struct ata_port *ap) u8 ata_dummy_irq_on (struct ata_port *ap) { return 0; } /** + * ata_irq_off - Disable interrupts on a port. + * @ap: Port on which interrupts are disabled. + * + * Disable interrupts on a legacy IDE device using MMIO or PIO, + * wait for idle, clear any pending interrupts. + * + * LOCKING: + * Inherited from caller. + */ +u8 ata_irq_off(struct ata_port *ap) +{ + struct ata_ioports *ioaddr = &ap->ioaddr; + u8 tmp; + + ap->ctl |= ATA_NIEN; + ap->last_ctl = ap->ctl; + + iowrite8(ap->ctl, ioaddr->ctl_addr); + + /* Under certain circumstances, some controllers raise IRQ on + * ATA_NIEN manipulation. Also, many controllers fail to mask + * previously pending IRQ on ATA_NIEN assertion. Clear it. + */ + tmp = ata_wait_idle(ap); + + ap->ops->irq_clear(ap); + + return tmp; +} + +u8 ata_dummy_irq_off (struct ata_port *ap) { return 0; } + +/** * ata_irq_ack - Acknowledge a device interrupt. * @ap: Port on which interrupts are enabled. * diff -Nrup 01_remove_leftover_irqon/drivers/ata/libata.h 02_add_irq_off/drivers/ata/libata.h --- 01_remove_leftover_irqon/drivers/ata/libata.h 2007-07-04 11:26:30.000000000 +0800 +++ 02_add_irq_off/drivers/ata/libata.h 2007-07-04 11:57:33.000000000 +0800 @@ -156,7 +156,5 @@ extern void ata_port_wait_eh(struct ata_ extern void ata_qc_schedule_eh(struct ata_queued_cmd *qc); /* libata-sff.c */ -extern u8 ata_irq_on(struct ata_port *ap); - #endif /* __LIBATA_H__ */ diff -Nrup 01_remove_leftover_irqon/include/linux/libata.h 02_add_irq_off/include/linux/libata.h --- 01_remove_leftover_irqon/include/linux/libata.h 2007-07-04 11:26:45.000000000 +0800 +++ 02_add_irq_off/include/linux/libata.h 2007-07-04 11:57:33.000000000 +0800 @@ -597,6 +597,7 @@ struct ata_port_operations { irq_handler_t irq_handler; void (*irq_clear) (struct ata_port *); u8 (*irq_on) (struct ata_port *); + u8 (*irq_off) (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); @@ -804,6 +805,8 @@ extern struct ata_device *ata_dev_pair(s extern int ata_do_set_mode(struct ata_port *ap, struct ata_device **r_failed_dev); extern u8 ata_irq_on(struct ata_port *ap); extern u8 ata_dummy_irq_on(struct ata_port *ap); +extern u8 ata_irq_off(struct ata_port *ap); +extern u8 ata_dummy_irq_off(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); - To unsubscribe from this list: send the line "unsubscribe linux-ide" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html