aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/ata
diff options
context:
space:
mode:
authorSergei Shtylyov <sergei.shtylyov@cogentembedded.com>2013-05-31 18:38:35 -0400
committerTejun Heo <tj@kernel.org>2013-06-02 03:54:45 -0400
commit52a2a1087b5924de00484f35ef5e2a73f61dbd22 (patch)
treeb1887001bdf51e25024fc288552d6bead78b6f1e /drivers/ata
parentfcce9a35f8faaa1f52236c554ef1b15d99a7537e (diff)
sata_rcar: fix interrupt handling
The driver's interrupt handling code is too picky in deciding whether it should handle an interrupt or not which causes completely unneeded spurious interrupts. Thus make sata_rcar_{ata|serr}_interrupt() *void*; add ATA status register read to sata_rcar_ata_interrupt() to clear an unexpected ATA interrupt -- it doesn't get cleared by writing to the SATAINTSTAT register in the interrupt mode we use. Also, in sata_rcar_ata_interrupt() we should check SATAINTSTAT register only for enabled interrupts and we should clear only those interrupts that we have read as active first time around, because else we have a race and risk clearing an interrupt that can occur between read and write of the SATAINTSTAT register and never registering it... Signed-off-by: Sergei Shtylyov <sergei.shtylyov@cogentembedded.com> Signed-off-by: Tejun Heo <tj@kernel.org> Cc: stable@vger.kernel.org
Diffstat (limited to 'drivers/ata')
-rw-r--r--drivers/ata/sata_rcar.c23
1 files changed, 11 insertions, 12 deletions
diff --git a/drivers/ata/sata_rcar.c b/drivers/ata/sata_rcar.c
index a8e091aafdde..249c8a289bfd 100644
--- a/drivers/ata/sata_rcar.c
+++ b/drivers/ata/sata_rcar.c
@@ -619,17 +619,16 @@ static struct ata_port_operations sata_rcar_port_ops = {
619 .bmdma_status = sata_rcar_bmdma_status, 619 .bmdma_status = sata_rcar_bmdma_status,
620}; 620};
621 621
622static int sata_rcar_serr_interrupt(struct ata_port *ap) 622static void sata_rcar_serr_interrupt(struct ata_port *ap)
623{ 623{
624 struct sata_rcar_priv *priv = ap->host->private_data; 624 struct sata_rcar_priv *priv = ap->host->private_data;
625 struct ata_eh_info *ehi = &ap->link.eh_info; 625 struct ata_eh_info *ehi = &ap->link.eh_info;
626 int freeze = 0; 626 int freeze = 0;
627 int handled = 0;
628 u32 serror; 627 u32 serror;
629 628
630 serror = ioread32(priv->base + SCRSERR_REG); 629 serror = ioread32(priv->base + SCRSERR_REG);
631 if (!serror) 630 if (!serror)
632 return 0; 631 return;
633 632
634 DPRINTK("SError @host_intr: 0x%x\n", serror); 633 DPRINTK("SError @host_intr: 0x%x\n", serror);
635 634
@@ -642,7 +641,6 @@ static int sata_rcar_serr_interrupt(struct ata_port *ap)
642 ata_ehi_push_desc(ehi, "%s", "hotplug"); 641 ata_ehi_push_desc(ehi, "%s", "hotplug");
643 642
644 freeze = serror & SERR_COMM_WAKE ? 0 : 1; 643 freeze = serror & SERR_COMM_WAKE ? 0 : 1;
645 handled = 1;
646 } 644 }
647 645
648 /* freeze or abort */ 646 /* freeze or abort */
@@ -650,11 +648,9 @@ static int sata_rcar_serr_interrupt(struct ata_port *ap)
650 ata_port_freeze(ap); 648 ata_port_freeze(ap);
651 else 649 else
652 ata_port_abort(ap); 650 ata_port_abort(ap);
653
654 return handled;
655} 651}
656 652
657static int sata_rcar_ata_interrupt(struct ata_port *ap) 653static void sata_rcar_ata_interrupt(struct ata_port *ap)
658{ 654{
659 struct ata_queued_cmd *qc; 655 struct ata_queued_cmd *qc;
660 int handled = 0; 656 int handled = 0;
@@ -663,7 +659,9 @@ static int sata_rcar_ata_interrupt(struct ata_port *ap)
663 if (qc) 659 if (qc)
664 handled |= ata_bmdma_port_intr(ap, qc); 660 handled |= ata_bmdma_port_intr(ap, qc);
665 661
666 return handled; 662 /* be sure to clear ATA interrupt */
663 if (!handled)
664 sata_rcar_check_status(ap);
667} 665}
668 666
669static irqreturn_t sata_rcar_interrupt(int irq, void *dev_instance) 667static irqreturn_t sata_rcar_interrupt(int irq, void *dev_instance)
@@ -678,20 +676,21 @@ static irqreturn_t sata_rcar_interrupt(int irq, void *dev_instance)
678 spin_lock_irqsave(&host->lock, flags); 676 spin_lock_irqsave(&host->lock, flags);
679 677
680 sataintstat = ioread32(priv->base + SATAINTSTAT_REG); 678 sataintstat = ioread32(priv->base + SATAINTSTAT_REG);
679 sataintstat &= SATA_RCAR_INT_MASK;
681 if (!sataintstat) 680 if (!sataintstat)
682 goto done; 681 goto done;
683 /* ack */ 682 /* ack */
684 iowrite32(sataintstat & ~SATA_RCAR_INT_MASK, 683 iowrite32(~sataintstat & 0x7ff, priv->base + SATAINTSTAT_REG);
685 priv->base + SATAINTSTAT_REG);
686 684
687 ap = host->ports[0]; 685 ap = host->ports[0];
688 686
689 if (sataintstat & SATAINTSTAT_ATA) 687 if (sataintstat & SATAINTSTAT_ATA)
690 handled |= sata_rcar_ata_interrupt(ap); 688 sata_rcar_ata_interrupt(ap);
691 689
692 if (sataintstat & SATAINTSTAT_SERR) 690 if (sataintstat & SATAINTSTAT_SERR)
693 handled |= sata_rcar_serr_interrupt(ap); 691 sata_rcar_serr_interrupt(ap);
694 692
693 handled = 1;
695done: 694done:
696 spin_unlock_irqrestore(&host->lock, flags); 695 spin_unlock_irqrestore(&host->lock, flags);
697 696