aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/scsi
diff options
context:
space:
mode:
authorTejun Heo <htejun@gmail.com>2005-08-22 04:12:45 -0400
committerJeff Garzik <jgarzik@pobox.com>2005-08-23 01:05:55 -0400
commit40e8c82c74b9be793601e098fd1313bc2632c5dc (patch)
treeb3c89b2aaa5d477e8db5acc9bf4ee6f31acf3db8 /drivers/scsi
parentc1389503710ef4b4e5d21bea284afde19e9619cf (diff)
[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 <htejun@gmail.com> Signed-off-by: Jeff Garzik <jgarzik@pobox.com>
Diffstat (limited to 'drivers/scsi')
-rw-r--r--drivers/scsi/libata-core.c34
1 files changed, 24 insertions, 10 deletions
diff --git a/drivers/scsi/libata-core.c b/drivers/scsi/libata-core.c
index c92439fe5dae..2f68563ac3a3 100644
--- a/drivers/scsi/libata-core.c
+++ b/drivers/scsi/libata-core.c
@@ -2402,6 +2402,26 @@ static int ata_sg_setup(struct ata_queued_cmd *qc)
2402} 2402}
2403 2403
2404/** 2404/**
2405 * ata_poll_qc_complete - turn irq back on and finish qc
2406 * @qc: Command to complete
2407 * @drv_stat: ATA status register content
2408 *
2409 * LOCKING:
2410 * None. (grabs host lock)
2411 */
2412
2413void ata_poll_qc_complete(struct ata_queued_cmd *qc, u8 drv_stat)
2414{
2415 struct ata_port *ap = qc->ap;
2416
2417 spin_lock_irq(&ap->host_set->lock);
2418 ap->flags &= ~ATA_FLAG_NOINTR;
2419 ata_irq_on(ap);
2420 ata_qc_complete(qc, drv_stat);
2421 spin_unlock_irq(&ap->host_set->lock);
2422}
2423
2424/**
2405 * ata_pio_poll - 2425 * ata_pio_poll -
2406 * @ap: 2426 * @ap:
2407 * 2427 *
@@ -2492,9 +2512,7 @@ static void ata_pio_complete (struct ata_port *ap)
2492 2512
2493 ap->pio_task_state = PIO_ST_IDLE; 2513 ap->pio_task_state = PIO_ST_IDLE;
2494 2514
2495 ata_irq_on(ap); 2515 ata_poll_qc_complete(qc, drv_stat);
2496
2497 ata_qc_complete(qc, drv_stat);
2498} 2516}
2499 2517
2500 2518
@@ -2844,9 +2862,7 @@ static void ata_pio_block(struct ata_port *ap)
2844 if ((status & ATA_DRQ) == 0) { 2862 if ((status & ATA_DRQ) == 0) {
2845 ap->pio_task_state = PIO_ST_IDLE; 2863 ap->pio_task_state = PIO_ST_IDLE;
2846 2864
2847 ata_irq_on(ap); 2865 ata_poll_qc_complete(qc, status);
2848
2849 ata_qc_complete(qc, status);
2850 return; 2866 return;
2851 } 2867 }
2852 2868
@@ -2876,9 +2892,7 @@ static void ata_pio_error(struct ata_port *ap)
2876 2892
2877 ap->pio_task_state = PIO_ST_IDLE; 2893 ap->pio_task_state = PIO_ST_IDLE;
2878 2894
2879 ata_irq_on(ap); 2895 ata_poll_qc_complete(qc, drv_stat | ATA_ERR);
2880
2881 ata_qc_complete(qc, drv_stat | ATA_ERR);
2882} 2896}
2883 2897
2884static void ata_pio_task(void *_data) 2898static void ata_pio_task(void *_data)
@@ -3791,7 +3805,7 @@ static void atapi_packet_task(void *_data)
3791 return; 3805 return;
3792 3806
3793err_out: 3807err_out:
3794 ata_qc_complete(qc, ATA_ERR); 3808 ata_poll_qc_complete(qc, ATA_ERR);
3795} 3809}
3796 3810
3797 3811