Skip to content

Commit

Permalink
libata sata_qstor workaround for spurious interrupts
Browse files Browse the repository at this point in the history
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 <mlord@pobox.com>
Signed-off-by: Jeff Garzik <jeff@garzik.org>
  • Loading branch information
Mark Lord authored and Jeff Garzik committed Nov 8, 2007
1 parent 12ee7d3 commit 904c7ba
Showing 1 changed file with 21 additions and 17 deletions.
38 changes: 21 additions & 17 deletions drivers/ata/sata_qstor.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -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");

Expand Down

0 comments on commit 904c7ba

Please sign in to comment.