Sophie

Sophie

distrib > Scientific%20Linux > 5x > x86_64 > by-pkgid > 27922b4260f65d317aabda37e42bbbff > files > 1550

kernel-2.6.18-238.el5.src.rpm

From: James Paradis <jparadis@redhat.com>
Date: Fri, 6 Mar 2009 15:37:24 -0500
Subject: [ide] fix interrupt flood at startup w/ESB2
Message-id: 753202734.68691236371844598.JavaMail.root@zmail01.collab.prod.int.phx2.redhat.com
O-Subject: Re: [RHEL5.4 PATCH] Fix interrupt flood at startup w/ESB2 IDE
Bugzilla: 438979
RH-Acked-by: David Milburn <dmilburn@redhat.com>

https://bugzilla.redhat.com/show_bug.cgi?id=438979

This patch was devised by Stratus to fix an interrupt flood we would get
when using the IDE function of
the ESB2.  Most of the libata code does the right thing with clearing the
interrupt bit when it's
expected (e.g. after handling a DMA), but we ran into a case where the bit
is unexpectedly set.  It
turns out that this controller has the quirk that the initial probe commands
will also set the interrupt
bit, even though we set the ATA_TFLAG_POLLING bit.  With the POLLING bit
clear, the interrupt handler
falls through without hitting a code path that clears the bit.  As a result
we keep getting bombarded with interrupts.

This patch clears the interrupt bit if we haven't handled the interrupt any
other way, and it fixes the
problem.

I could use some help here, though: I'm not a libata expert, and there were
some comments by Alan Cox in
the bugzilla that I didn't quite understand... could somebody who knows
libata help explain them to me?
He seems to imply that maybe we want to fix this a different way...

dmilburn and I have been going back and forth on this in bugzilla.  Try this new patch; it treats this issue as a quirk and only clears the irq on specified hardware model(s):

diff --git a/drivers/ata/ata_piix.c b/drivers/ata/ata_piix.c
index 71f55d1..ff18ba4 100644
--- a/drivers/ata/ata_piix.c
+++ b/drivers/ata/ata_piix.c
@@ -1547,6 +1547,12 @@ static int __devinit piix_init_one(struct pci_dev *pdev,
 	}
 
 	pci_set_master(pdev);
+
+	/* ESB2 may generate DMA interrupts in PIO state */
+	if (pdev->vendor == PCI_VENDOR_ID_INTEL &&
+	    pdev->device == PCI_DEVICE_ID_INTEL_ESB2_18)
+		host->flags |= ATA_HOST_ATAPI_SPURIOUS_INT;
+
 	return ata_pci_sff_activate_host(host, ata_sff_interrupt, &piix_sht);
 }
 
diff --git a/drivers/ata/libata-sff.c b/drivers/ata/libata-sff.c
index afb816a..5fe674f 100644
--- a/drivers/ata/libata-sff.c
+++ b/drivers/ata/libata-sff.c
@@ -1651,6 +1651,8 @@ irqreturn_t ata_sff_interrupt(int irq, void *dev_instance, struct pt_regs *pt_re
 			if (qc && (!(qc->tf.flags & ATA_TFLAG_POLLING)) &&
 			    (qc->flags & ATA_QCFLAG_ACTIVE))
 				handled |= ata_sff_host_intr(ap, qc);
+			else if(unlikely(host->flags & ATA_HOST_ATAPI_SPURIOUS_INT))
+				ap->ops->sff_irq_clear(ap);
 		}
 	}
 
diff --git a/include/linux/libata.h b/include/linux/libata.h
index 53bcd7d..2b4509b 100644
--- a/include/linux/libata.h
+++ b/include/linux/libata.h
@@ -237,6 +237,7 @@ enum {
 	/* host set flags */
 	ATA_HOST_SIMPLEX	= (1 << 0),	/* Host is simplex, one DMA channel per host only */
 	ATA_HOST_STARTED	= (1 << 1),	/* Host started */
+	ATA_HOST_ATAPI_SPURIOUS_INT = (1 << 2),
 
 	/* bits 24:31 of host->flags are reserved for LLD specific flags */