tree b3c89b2aaa5d477e8db5acc9bf4ee6f31acf3db8 parent c1389503710ef4b4e5d21bea284afde19e9619cf author Tejun Heo <[EMAIL PROTECTED]> Mon, 22 Aug 2005 17:12:45 +0900 committer Jeff Garzik <[EMAIL PROTECTED]> Tue, 23 Aug 2005 09:05:55 -0400
[PATCH] libata: implement ata_poll_qc_complete and use it in polling functions [PATCH libata-dev-2.6:upstream] implement ata_poll_qc_complete and use it in polling functions Previously, libata polling functions turned irq back on and completed qc commands without holding host lock. This creates a race condition between the polling task and interrupts from other ports on the same host set or spurious interrupt from itself. This patch implements ata_poll_qc_complete which enables irq and completes qc atomically and convert all polling functions. Note: atapi_packet_task() didn't use to turn irq back on or clear ATA_FLAG_NOINTR on error exits. This patch makes it use ata_poll_qc_complete which does both. Note: With this change, ALL invocations of ata_qc_complete() are now done under host_set lock. Signed-off-by: Tejun Heo <[EMAIL PROTECTED]> Signed-off-by: Jeff Garzik <[EMAIL PROTECTED]> drivers/scsi/libata-core.c | 34 ++++++++++++++++++++++++---------- 1 files changed, 24 insertions(+), 10 deletions(-) diff --git a/drivers/scsi/libata-core.c b/drivers/scsi/libata-core.c --- a/drivers/scsi/libata-core.c +++ b/drivers/scsi/libata-core.c @@ -2402,6 +2402,26 @@ static int ata_sg_setup(struct ata_queue } /** + * ata_poll_qc_complete - turn irq back on and finish qc + * @qc: Command to complete + * @drv_stat: ATA status register content + * + * LOCKING: + * None. (grabs host lock) + */ + +void ata_poll_qc_complete(struct ata_queued_cmd *qc, u8 drv_stat) +{ + struct ata_port *ap = qc->ap; + + spin_lock_irq(&ap->host_set->lock); + ap->flags &= ~ATA_FLAG_NOINTR; + ata_irq_on(ap); + ata_qc_complete(qc, drv_stat); + spin_unlock_irq(&ap->host_set->lock); +} + +/** * ata_pio_poll - * @ap: * @@ -2492,9 +2512,7 @@ static void ata_pio_complete (struct ata ap->pio_task_state = PIO_ST_IDLE; - ata_irq_on(ap); - - ata_qc_complete(qc, drv_stat); + ata_poll_qc_complete(qc, drv_stat); } @@ -2844,9 +2862,7 @@ static void ata_pio_block(struct ata_por if ((status & ATA_DRQ) == 0) { ap->pio_task_state = PIO_ST_IDLE; - ata_irq_on(ap); - - ata_qc_complete(qc, status); + ata_poll_qc_complete(qc, status); return; } @@ -2876,9 +2892,7 @@ static void ata_pio_error(struct ata_por ap->pio_task_state = PIO_ST_IDLE; - ata_irq_on(ap); - - ata_qc_complete(qc, drv_stat | ATA_ERR); + ata_poll_qc_complete(qc, drv_stat | ATA_ERR); } static void ata_pio_task(void *_data) @@ -3791,7 +3805,7 @@ static void atapi_packet_task(void *_dat return; err_out: - ata_qc_complete(qc, ATA_ERR); + ata_poll_qc_complete(qc, ATA_ERR); } - To unsubscribe from this list: send the line "unsubscribe git-commits-head" in the body of a message to [EMAIL PROTECTED] More majordomo info at http://vger.kernel.org/majordomo-info.html