aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/scsi/libata-core.c
diff options
context:
space:
mode:
authorJeff Garzik <jgarzik@pobox.com>2005-08-25 22:01:20 -0400
committerJeff Garzik <jgarzik@pobox.com>2005-08-25 22:01:20 -0400
commitb8f6153ee421014f42b620238f4203a4106db309 (patch)
treeebc9eac4517325be0a91a4e2b2cb38f08d36812e /drivers/scsi/libata-core.c
parent617e44fdfd7ee3d53388ab295d9411b826437ce9 (diff)
libata: fix EH locking
Wrap ata_qc_complete() calls in EH context in spinlocks, to prevent races (mainly in ATAPI code paths).
Diffstat (limited to 'drivers/scsi/libata-core.c')
-rw-r--r--drivers/scsi/libata-core.c14
1 files changed, 12 insertions, 2 deletions
diff --git a/drivers/scsi/libata-core.c b/drivers/scsi/libata-core.c
index 157a3e914cb7..ec7bff73ae18 100644
--- a/drivers/scsi/libata-core.c
+++ b/drivers/scsi/libata-core.c
@@ -2388,12 +2388,13 @@ static int ata_sg_setup(struct ata_queued_cmd *qc)
2388void ata_poll_qc_complete(struct ata_queued_cmd *qc, u8 drv_stat) 2388void ata_poll_qc_complete(struct ata_queued_cmd *qc, u8 drv_stat)
2389{ 2389{
2390 struct ata_port *ap = qc->ap; 2390 struct ata_port *ap = qc->ap;
2391 unsigned long flags;
2391 2392
2392 spin_lock_irq(&ap->host_set->lock); 2393 spin_lock_irqsave(&ap->host_set->lock, flags);
2393 ap->flags &= ~ATA_FLAG_NOINTR; 2394 ap->flags &= ~ATA_FLAG_NOINTR;
2394 ata_irq_on(ap); 2395 ata_irq_on(ap);
2395 ata_qc_complete(qc, drv_stat); 2396 ata_qc_complete(qc, drv_stat);
2396 spin_unlock_irq(&ap->host_set->lock); 2397 spin_unlock_irqrestore(&ap->host_set->lock, flags);
2397} 2398}
2398 2399
2399/** 2400/**
@@ -2973,8 +2974,10 @@ static void atapi_request_sense(struct ata_port *ap, struct ata_device *dev,
2973static void ata_qc_timeout(struct ata_queued_cmd *qc) 2974static void ata_qc_timeout(struct ata_queued_cmd *qc)
2974{ 2975{
2975 struct ata_port *ap = qc->ap; 2976 struct ata_port *ap = qc->ap;
2977 struct ata_host_set *host_set = ap->host_set;
2976 struct ata_device *dev = qc->dev; 2978 struct ata_device *dev = qc->dev;
2977 u8 host_stat = 0, drv_stat; 2979 u8 host_stat = 0, drv_stat;
2980 unsigned long flags;
2978 2981
2979 DPRINTK("ENTER\n"); 2982 DPRINTK("ENTER\n");
2980 2983
@@ -2985,7 +2988,9 @@ static void ata_qc_timeout(struct ata_queued_cmd *qc)
2985 if (!(cmd->eh_eflags & SCSI_EH_CANCEL_CMD)) { 2988 if (!(cmd->eh_eflags & SCSI_EH_CANCEL_CMD)) {
2986 2989
2987 /* finish completing original command */ 2990 /* finish completing original command */
2991 spin_lock_irqsave(&host_set->lock, flags);
2988 __ata_qc_complete(qc); 2992 __ata_qc_complete(qc);
2993 spin_unlock_irqrestore(&host_set->lock, flags);
2989 2994
2990 atapi_request_sense(ap, dev, cmd); 2995 atapi_request_sense(ap, dev, cmd);
2991 2996
@@ -2996,6 +3001,8 @@ static void ata_qc_timeout(struct ata_queued_cmd *qc)
2996 } 3001 }
2997 } 3002 }
2998 3003
3004 spin_lock_irqsave(&host_set->lock, flags);
3005
2999 /* hack alert! We cannot use the supplied completion 3006 /* hack alert! We cannot use the supplied completion
3000 * function from inside the ->eh_strategy_handler() thread. 3007 * function from inside the ->eh_strategy_handler() thread.
3001 * libata is the only user of ->eh_strategy_handler() in 3008 * libata is the only user of ->eh_strategy_handler() in
@@ -3029,6 +3036,9 @@ static void ata_qc_timeout(struct ata_queued_cmd *qc)
3029 ata_qc_complete(qc, drv_stat); 3036 ata_qc_complete(qc, drv_stat);
3030 break; 3037 break;
3031 } 3038 }
3039
3040 spin_unlock_irqrestore(&host_set->lock, flags);
3041
3032out: 3042out:
3033 DPRINTK("EXIT\n"); 3043 DPRINTK("EXIT\n");
3034} 3044}