aboutsummaryrefslogtreecommitdiffstats
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
parent617e44fdfd7ee3d53388ab295d9411b826437ce9 (diff)
libata: fix EH locking
Wrap ata_qc_complete() calls in EH context in spinlocks, to prevent races (mainly in ATAPI code paths).
-rw-r--r--drivers/scsi/ahci.c7
-rw-r--r--drivers/scsi/libata-core.c14
-rw-r--r--drivers/scsi/sata_promise.c5
-rw-r--r--drivers/scsi/sata_sx4.c5
4 files changed, 28 insertions, 3 deletions
diff --git a/drivers/scsi/ahci.c b/drivers/scsi/ahci.c
index 348493982b56..841f4e2cfe08 100644
--- a/drivers/scsi/ahci.c
+++ b/drivers/scsi/ahci.c
@@ -586,12 +586,16 @@ static void ahci_intr_error(struct ata_port *ap, u32 irq_stat)
586 586
587static void ahci_eng_timeout(struct ata_port *ap) 587static void ahci_eng_timeout(struct ata_port *ap)
588{ 588{
589 void *mmio = ap->host_set->mmio_base; 589 struct ata_host_set *host_set = ap->host_set;
590 void *mmio = host_set->mmio_base;
590 void *port_mmio = ahci_port_base(mmio, ap->port_no); 591 void *port_mmio = ahci_port_base(mmio, ap->port_no);
591 struct ata_queued_cmd *qc; 592 struct ata_queued_cmd *qc;
593 unsigned long flags;
592 594
593 DPRINTK("ENTER\n"); 595 DPRINTK("ENTER\n");
594 596
597 spin_lock_irqsave(&host_set->lock, flags);
598
595 ahci_intr_error(ap, readl(port_mmio + PORT_IRQ_STAT)); 599 ahci_intr_error(ap, readl(port_mmio + PORT_IRQ_STAT));
596 600
597 qc = ata_qc_from_tag(ap, ap->active_tag); 601 qc = ata_qc_from_tag(ap, ap->active_tag);
@@ -609,6 +613,7 @@ static void ahci_eng_timeout(struct ata_port *ap)
609 ata_qc_complete(qc, ATA_ERR); 613 ata_qc_complete(qc, ATA_ERR);
610 } 614 }
611 615
616 spin_unlock_irqrestore(&host_set->lock, flags);
612} 617}
613 618
614static inline int ahci_host_intr(struct ata_port *ap, struct ata_queued_cmd *qc) 619static inline int ahci_host_intr(struct ata_port *ap, struct ata_queued_cmd *qc)
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}
diff --git a/drivers/scsi/sata_promise.c b/drivers/scsi/sata_promise.c
index defcc1fb3f16..b8dc49fed769 100644
--- a/drivers/scsi/sata_promise.c
+++ b/drivers/scsi/sata_promise.c
@@ -325,11 +325,15 @@ static void pdc_qc_prep(struct ata_queued_cmd *qc)
325 325
326static void pdc_eng_timeout(struct ata_port *ap) 326static void pdc_eng_timeout(struct ata_port *ap)
327{ 327{
328 struct ata_host_set *host_set = ap->host_set;
328 u8 drv_stat; 329 u8 drv_stat;
329 struct ata_queued_cmd *qc; 330 struct ata_queued_cmd *qc;
331 unsigned long flags;
330 332
331 DPRINTK("ENTER\n"); 333 DPRINTK("ENTER\n");
332 334
335 spin_lock_irqsave(&host_set->lock, flags);
336
333 qc = ata_qc_from_tag(ap, ap->active_tag); 337 qc = ata_qc_from_tag(ap, ap->active_tag);
334 if (!qc) { 338 if (!qc) {
335 printk(KERN_ERR "ata%u: BUG: timeout without command\n", 339 printk(KERN_ERR "ata%u: BUG: timeout without command\n",
@@ -363,6 +367,7 @@ static void pdc_eng_timeout(struct ata_port *ap)
363 } 367 }
364 368
365out: 369out:
370 spin_unlock_irqrestore(&host_set->lock, flags);
366 DPRINTK("EXIT\n"); 371 DPRINTK("EXIT\n");
367} 372}
368 373
diff --git a/drivers/scsi/sata_sx4.c b/drivers/scsi/sata_sx4.c
index e2db499f22dd..a20d4285090a 100644
--- a/drivers/scsi/sata_sx4.c
+++ b/drivers/scsi/sata_sx4.c
@@ -848,10 +848,14 @@ static irqreturn_t pdc20621_interrupt (int irq, void *dev_instance, struct pt_re
848static void pdc_eng_timeout(struct ata_port *ap) 848static void pdc_eng_timeout(struct ata_port *ap)
849{ 849{
850 u8 drv_stat; 850 u8 drv_stat;
851 struct ata_host_set *host_set = ap->host_set;
851 struct ata_queued_cmd *qc; 852 struct ata_queued_cmd *qc;
853 unsigned long flags;
852 854
853 DPRINTK("ENTER\n"); 855 DPRINTK("ENTER\n");
854 856
857 spin_lock_irqsave(&host_set->lock, flags);
858
855 qc = ata_qc_from_tag(ap, ap->active_tag); 859 qc = ata_qc_from_tag(ap, ap->active_tag);
856 if (!qc) { 860 if (!qc) {
857 printk(KERN_ERR "ata%u: BUG: timeout without command\n", 861 printk(KERN_ERR "ata%u: BUG: timeout without command\n",
@@ -885,6 +889,7 @@ static void pdc_eng_timeout(struct ata_port *ap)
885 } 889 }
886 890
887out: 891out:
892 spin_unlock_irqrestore(&host_set->lock, flags);
888 DPRINTK("EXIT\n"); 893 DPRINTK("EXIT\n");
889} 894}
890 895