[kernel] r15521 - in dists/sid/linux-2.6/debian: . patches/bugfix/all patches/series

Maximilian Attems maks at alioth.debian.org
Sun Apr 18 03:54:18 UTC 2010


Author: maks
Date: Sun Apr 18 03:54:15 2010
New Revision: 15521

Log:
libata,ata_piix: detect and clear spurious IRQs

backported fix by tejun seen in opensuse.

Added:
   dists/sid/linux-2.6/debian/patches/bugfix/all/libata-ata_piix-clear-spurious-IRQ.patch
Modified:
   dists/sid/linux-2.6/debian/changelog
   dists/sid/linux-2.6/debian/patches/series/12

Modified: dists/sid/linux-2.6/debian/changelog
==============================================================================
--- dists/sid/linux-2.6/debian/changelog	Sun Apr 18 03:07:03 2010	(r15520)
+++ dists/sid/linux-2.6/debian/changelog	Sun Apr 18 03:54:15 2010	(r15521)
@@ -28,6 +28,7 @@
   * Update openvz patch to 6b5607eeec54. (closes: #574598)
   * Reenable nouveau autoloading.
   * reiserfs: Fix permissions on .reiserfs_priv. CVE-2010-1146
+  * libata,ata_piix: detect and clear spurious IRQs.
 
   [ dann frazier ]
   * Add DRBD backport

Added: dists/sid/linux-2.6/debian/patches/bugfix/all/libata-ata_piix-clear-spurious-IRQ.patch
==============================================================================
--- /dev/null	00:00:00 1970	(empty, because file is newly added)
+++ dists/sid/linux-2.6/debian/patches/bugfix/all/libata-ata_piix-clear-spurious-IRQ.patch	Sun Apr 18 03:54:15 2010	(r15521)
@@ -0,0 +1,148 @@
+From: Tejun Heo <tj at kernel.org>
+Subject: libata,ata_piix: detect and clear spurious IRQs
+Patch-Mainline: Backported from changes pending for 2.6.34
+References: bnc#445872, bnc#589449
+
+Backport spurious IRQ handling from 2.6.34.  It isn't exactly the same
+form in that it doesn't use callbacks but implements custom
+piix_interrupt() but should function the same.  This protects ata_piix
+against nobody-cared which gets reported not so rarely.
+
+Signed-off-by: Tejun Heo <tj at kernel.org>
+Signed-off-by: Tejun Heo <teheo at suse.de>
+---
+ drivers/ata/ata_piix.c   |   76 ++++++++++++++++++++++++++++++++++++++++++++++-
+ drivers/ata/libata-sff.c |   12 ++++++-
+ 2 files changed, 85 insertions(+), 3 deletions(-)
+
+Index: linux-2.6.32-SLE11-SP1/drivers/ata/ata_piix.c
+===================================================================
+--- linux-2.6.32-SLE11-SP1.orig/drivers/ata/ata_piix.c
++++ linux-2.6.32-SLE11-SP1/drivers/ata/ata_piix.c
+@@ -949,6 +949,80 @@ static int piix_sidpr_scr_read(struct at
+ 	return 0;
+ }
+ 
++static irqreturn_t piix_interrupt(int irq, void *dev_instance)
++{
++	struct ata_host *host = dev_instance;
++	bool retried = false;
++	unsigned int i;
++	unsigned int handled = 0, polling = 0, idle = 0;
++	unsigned long flags;
++
++	spin_lock_irqsave(&host->lock, flags);
++retry:
++	handled = idle = polling = 0;
++	for (i = 0; i < host->n_ports; i++) {
++		struct ata_port *ap = host->ports[i];
++		struct ata_queued_cmd *qc;
++
++		if (ata_port_is_dummy(ap))
++			continue;
++
++		qc = ata_qc_from_tag(ap, ap->link.active_tag);
++		if (qc) {
++			if (!(qc->tf.flags & ATA_TFLAG_POLLING))
++				handled |= ata_sff_host_intr(ap, qc);
++			else
++				polling |= 1 << i;
++		} else
++			idle |= 1 << i;
++	}
++
++	/*
++	 * If no port was expecting IRQ but the controller is actually
++	 * asserting IRQ line, nobody cared will ensue.  Check IRQ
++	 * pending status if available and clear spurious IRQ.
++	 */
++	if (!handled && !retried) {
++		bool retry = false;
++
++		for (i = 0; i < host->n_ports; i++) {
++			struct ata_port *ap = host->ports[i];
++			u8 host_stat;
++
++			if (polling & (1 << i))
++				continue;
++
++			if (unlikely(!ap->ioaddr.bmdma_addr))
++				continue;
++
++			host_stat = ap->ops->bmdma_status(ap);
++			if (!(host_stat & ATA_DMA_INTR))
++				continue;
++
++			if (idle & (1 << i)) {
++				ap->ops->sff_check_status(ap);
++				ap->ops->sff_irq_clear(ap);
++			} else {
++				/* clear INTRQ and check if BUSY cleared */
++				if (!(ap->ops->sff_check_status(ap) & ATA_BUSY))
++					retry |= true;
++				/*
++				 * With command in flight, we can't do
++				 * sff_irq_clear() w/o racing with completion.
++				 */
++			}
++		}
++		if (retry) {
++			retried = true;
++			goto retry;
++		}
++	}
++
++	spin_unlock_irqrestore(&host->lock, flags);
++
++	return IRQ_RETVAL(handled);
++}
++
+ static int piix_sidpr_scr_write(struct ata_link *link,
+ 				unsigned int reg, u32 val)
+ {
+@@ -1607,7 +1681,7 @@ static int __devinit piix_init_one(struc
+ 	host->flags |= ATA_HOST_PARALLEL_SCAN;
+ 
+ 	pci_set_master(pdev);
+-	return ata_pci_sff_activate_host(host, ata_sff_interrupt, &piix_sht);
++	return ata_pci_sff_activate_host(host, piix_interrupt, &piix_sht);
+ }
+ 
+ static void piix_remove_one(struct pci_dev *pdev)
+Index: linux-2.6.32-SLE11-SP1/drivers/ata/libata-sff.c
+===================================================================
+--- linux-2.6.32-SLE11-SP1.orig/drivers/ata/libata-sff.c
++++ linux-2.6.32-SLE11-SP1/drivers/ata/libata-sff.c
+@@ -1667,6 +1667,7 @@ unsigned int ata_sff_host_intr(struct at
+ {
+ 	struct ata_eh_info *ehi = &ap->link.eh_info;
+ 	u8 status, host_stat = 0;
++	bool bmdma_stopped = false;
+ 
+ 	VPRINTK("ata%u: protocol %d task_state %d\n",
+ 		ap->print_id, qc->tf.protocol, ap->hsm_task_state);
+@@ -1699,6 +1700,7 @@ unsigned int ata_sff_host_intr(struct at
+ 
+ 			/* before we do anything else, clear DMA-Start bit */
+ 			ap->ops->bmdma_stop(qc);
++			bmdma_stopped = true;
+ 
+ 			if (unlikely(host_stat & ATA_DMA_ERR)) {
+ 				/* error when transfering data to/from memory */
+@@ -1716,8 +1718,14 @@ unsigned int ata_sff_host_intr(struct at
+ 
+ 	/* check main status, clearing INTRQ if needed */
+ 	status = ata_sff_irq_status(ap);
+-	if (status & ATA_BUSY)
+-		goto idle_irq;
++	if (status & ATA_BUSY) {
++		if (bmdma_stopped) {
++			/* BMDMA engine is already stopped, we're screwed */
++			qc->err_mask |= AC_ERR_HSM;
++			ap->hsm_task_state = HSM_ST_ERR;
++		} else
++			goto idle_irq;
++	}
+ 
+ 	/* ack bmdma irq events */
+ 	ap->ops->sff_irq_clear(ap);

Modified: dists/sid/linux-2.6/debian/patches/series/12
==============================================================================
--- dists/sid/linux-2.6/debian/patches/series/12	Sun Apr 18 03:07:03 2010	(r15520)
+++ dists/sid/linux-2.6/debian/patches/series/12	Sun Apr 18 03:54:15 2010	(r15521)
@@ -8,3 +8,4 @@
 + bugfix/all/forcedeth-fix-tx-limit2-flag-check.patch
 - bugfix/all/drivers-gpu-nouveau-no-udev-auto-loading.patch
 + bugfix/all/reiserfs-fix-permissions-on-reiserfs_priv.patch
++ bugfix/all/libata-ata_piix-clear-spurious-IRQ.patch



More information about the Kernel-svn-changes mailing list