Gitweb:     
http://git.kernel.org/git/?p=linux/kernel/git/torvalds/linux-2.6.git;a=commit;h=904c7bad994e6e7f9997174e0b33fcc521862136
Commit:     904c7bad994e6e7f9997174e0b33fcc521862136
Parent:     12ee7d3ceb08e9ab99a6c17c5c6a387645a32658
Author:     Mark Lord <[EMAIL PROTECTED]>
AuthorDate: Wed Nov 7 10:53:41 2007 -0500
Committer:  Jeff Garzik <[EMAIL PROTECTED]>
CommitDate: Thu Nov 8 13:08:41 2007 -0500

    libata sata_qstor workaround for spurious interrupts
    
    sata_qstor workaround for spurious interrupts.
    
    The qstor hardware generates spurious interrupts from time to time when
    switching in and out of packet mode.  These eventually result in the
    IRQ being disabled, which kills other devices sharing this IRQ with us.
    
    This workaround isn't perfect, but it's about the best we can do for
    this hardware.  Spurious interrupts will still happen, but won't be
    logged as such, and therefore won't cause the IRQ to be inadvertently
    disabled.
    
    Signed-off-by:  Mark Lord <[EMAIL PROTECTED]>
    Signed-off-by: Jeff Garzik <[EMAIL PROTECTED]>
---
 drivers/ata/sata_qstor.c |   38 +++++++++++++++++++++-----------------
 1 files changed, 21 insertions(+), 17 deletions(-)

diff --git a/drivers/ata/sata_qstor.c b/drivers/ata/sata_qstor.c
index 9d3128c..7446a33 100644
--- a/drivers/ata/sata_qstor.c
+++ b/drivers/ata/sata_qstor.c
@@ -425,24 +425,27 @@ static inline unsigned int qs_intr_mmio(struct ata_host 
*host)
                if (ap &&
                    !(ap->flags & ATA_FLAG_DISABLED)) {
                        struct ata_queued_cmd *qc;
-                       struct qs_port_priv *pp = ap->private_data;
-                       if (!pp || pp->state != qs_state_mmio)
-                               continue;
+                       struct qs_port_priv *pp;
                        qc = ata_qc_from_tag(ap, ap->link.active_tag);
-                       if (qc && (!(qc->tf.flags & ATA_TFLAG_POLLING))) {
-
-                               /* check main status, clearing INTRQ */
-                               u8 status = ata_check_status(ap);
-                               if ((status & ATA_BUSY))
-                                       continue;
-                               DPRINTK("ata%u: protocol %d (dev_stat 0x%X)\n",
-                                       ap->print_id, qc->tf.protocol, status);
-
-                               /* complete taskfile transaction */
-                               qc->err_mask |= ac_err_mask(status);
-                               ata_qc_complete(qc);
+                       if (!qc || !(qc->flags & ATA_QCFLAG_ACTIVE)) {
+                               /*
+                                * The qstor hardware generates spurious
+                                * interrupts from time to time when switching
+                                * in and out of packet mode.
+                                * There's no obvious way to know if we're
+                                * here now due to that, so just ack the irq
+                                * and pretend we knew it was ours.. (ugh).
+                                * This does not affect packet mode.
+                                */
+                               ata_check_status(ap);
                                handled = 1;
+                               continue;
                        }
+                       pp = ap->private_data;
+                       if (!pp || pp->state != qs_state_mmio)
+                               continue;
+                       if (!(qc->tf.flags & ATA_TFLAG_POLLING))
+                               handled |= ata_host_intr(ap, qc);
                }
        }
        return handled;
@@ -452,12 +455,13 @@ static irqreturn_t qs_intr(int irq, void *dev_instance)
 {
        struct ata_host *host = dev_instance;
        unsigned int handled = 0;
+       unsigned long flags;
 
        VPRINTK("ENTER\n");
 
-       spin_lock(&host->lock);
+       spin_lock_irqsave(&host->lock, flags);
        handled  = qs_intr_pkt(host) | qs_intr_mmio(host);
-       spin_unlock(&host->lock);
+       spin_unlock_irqrestore(&host->lock, flags);
 
        VPRINTK("EXIT\n");
 
-
To unsubscribe from this list: send the line "unsubscribe git-commits-head" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Reply via email to