aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/ata/sata_mv.c
diff options
context:
space:
mode:
authorMark Lord <liml@rtr.ca>2009-04-06 12:30:43 -0400
committerJeff Garzik <jgarzik@redhat.com>2009-04-06 20:13:35 -0400
commit933cb8e5fcdebd4b666165e3f039f814d62b0e52 (patch)
treeb9ebdf51d740e9844876a04bd742a8b33eab2a89 /drivers/ata/sata_mv.c
parent44c65d169c5d2e5c872581ebc65f12710d7c3b71 (diff)
sata_mv: fix irq mask races
Prevent racing on the main interrupt mask during port_start and port_stop. Otherwise, we end up with IRQs masked on inactive ports, and hotplug insertions then get missed later on. Found while debugging (out of tree) target mode operations, but the bug is present and impacting mainline as well. This patch should also be considered for -stable. Signed-off-by: Mark Lord <mlord@pobox.com> Signed-off-by: Jeff Garzik <jgarzik@redhat.com>
Diffstat (limited to 'drivers/ata/sata_mv.c')
-rw-r--r--drivers/ata/sata_mv.c9
1 files changed, 9 insertions, 0 deletions
diff --git a/drivers/ata/sata_mv.c b/drivers/ata/sata_mv.c
index be9ae4fc5cbe..8245c82505cc 100644
--- a/drivers/ata/sata_mv.c
+++ b/drivers/ata/sata_mv.c
@@ -1575,6 +1575,7 @@ static int mv_port_start(struct ata_port *ap)
1575 struct device *dev = ap->host->dev; 1575 struct device *dev = ap->host->dev;
1576 struct mv_host_priv *hpriv = ap->host->private_data; 1576 struct mv_host_priv *hpriv = ap->host->private_data;
1577 struct mv_port_priv *pp; 1577 struct mv_port_priv *pp;
1578 unsigned long flags;
1578 int tag; 1579 int tag;
1579 1580
1580 pp = devm_kzalloc(dev, sizeof(*pp), GFP_KERNEL); 1581 pp = devm_kzalloc(dev, sizeof(*pp), GFP_KERNEL);
@@ -1610,8 +1611,12 @@ static int mv_port_start(struct ata_port *ap)
1610 pp->sg_tbl_dma[tag] = pp->sg_tbl_dma[0]; 1611 pp->sg_tbl_dma[tag] = pp->sg_tbl_dma[0];
1611 } 1612 }
1612 } 1613 }
1614
1615 spin_lock_irqsave(ap->lock, flags);
1613 mv_save_cached_regs(ap); 1616 mv_save_cached_regs(ap);
1614 mv_edma_cfg(ap, 0, 0); 1617 mv_edma_cfg(ap, 0, 0);
1618 spin_unlock_irqrestore(ap->lock, flags);
1619
1615 return 0; 1620 return 0;
1616 1621
1617out_port_free_dma_mem: 1622out_port_free_dma_mem:
@@ -1630,8 +1635,12 @@ out_port_free_dma_mem:
1630 */ 1635 */
1631static void mv_port_stop(struct ata_port *ap) 1636static void mv_port_stop(struct ata_port *ap)
1632{ 1637{
1638 unsigned long flags;
1639
1640 spin_lock_irqsave(ap->lock, flags);
1633 mv_stop_edma(ap); 1641 mv_stop_edma(ap);
1634 mv_enable_port_irqs(ap, 0); 1642 mv_enable_port_irqs(ap, 0);
1643 spin_unlock_irqrestore(ap->lock, flags);
1635 mv_port_free_dma_mem(ap); 1644 mv_port_free_dma_mem(ap);
1636} 1645}
1637 1646