Commit 6d3c30ef authored by Mark Lord's avatar Mark Lord Committed by Jeff Garzik

sata_mv: msi masking fix (v2)

Enable reliable use of Message-Signaled Interrupts (MSI) in sata_mv
by masking further chip interrupts within the main interrupt handler.

Based upon a suggestion by Grant Grundler.
MSI is working reliably in all of my test systems here now.
Signed-off-by: default avatarMark Lord <mlord@pobox.com>
Reviewed-by: default avatarGrant Grundler <grundler@google.com>
Signed-off-by: default avatarJeff Garzik <jgarzik@redhat.com>
parent 5d0fb2e7
...@@ -33,8 +33,6 @@ ...@@ -33,8 +33,6 @@
* *
* --> ATAPI support (Marvell claims the 60xx/70xx chips can do it). * --> ATAPI support (Marvell claims the 60xx/70xx chips can do it).
* *
* --> Investigate problems with PCI Message Signalled Interrupts (MSI).
*
* --> Develop a low-power-consumption strategy, and implement it. * --> Develop a low-power-consumption strategy, and implement it.
* *
* --> [Experiment, low priority] Investigate interrupt coalescing. * --> [Experiment, low priority] Investigate interrupt coalescing.
...@@ -70,7 +68,7 @@ ...@@ -70,7 +68,7 @@
#include <linux/libata.h> #include <linux/libata.h>
#define DRV_NAME "sata_mv" #define DRV_NAME "sata_mv"
#define DRV_VERSION "1.24" #define DRV_VERSION "1.25"
enum { enum {
/* BAR's are enumerated in terms of pci_resource_start() terms */ /* BAR's are enumerated in terms of pci_resource_start() terms */
...@@ -2199,9 +2197,15 @@ static irqreturn_t mv_interrupt(int irq, void *dev_instance) ...@@ -2199,9 +2197,15 @@ static irqreturn_t mv_interrupt(int irq, void *dev_instance)
struct ata_host *host = dev_instance; struct ata_host *host = dev_instance;
struct mv_host_priv *hpriv = host->private_data; struct mv_host_priv *hpriv = host->private_data;
unsigned int handled = 0; unsigned int handled = 0;
int using_msi = hpriv->hp_flags & MV_HP_FLAG_MSI;
u32 main_irq_cause, pending_irqs; u32 main_irq_cause, pending_irqs;
spin_lock(&host->lock); spin_lock(&host->lock);
/* for MSI: block new interrupts while in here */
if (using_msi)
writel(0, hpriv->main_irq_mask_addr);
main_irq_cause = readl(hpriv->main_irq_cause_addr); main_irq_cause = readl(hpriv->main_irq_cause_addr);
pending_irqs = main_irq_cause & hpriv->main_irq_mask; pending_irqs = main_irq_cause & hpriv->main_irq_mask;
/* /*
...@@ -2215,6 +2219,11 @@ static irqreturn_t mv_interrupt(int irq, void *dev_instance) ...@@ -2215,6 +2219,11 @@ static irqreturn_t mv_interrupt(int irq, void *dev_instance)
handled = mv_host_intr(host, pending_irqs); handled = mv_host_intr(host, pending_irqs);
} }
spin_unlock(&host->lock); spin_unlock(&host->lock);
/* for MSI: unmask; interrupt cause bits will retrigger now */
if (using_msi)
writel(hpriv->main_irq_mask, hpriv->main_irq_mask_addr);
return IRQ_RETVAL(handled); return IRQ_RETVAL(handled);
} }
...@@ -3417,9 +3426,9 @@ static int mv_pci_init_one(struct pci_dev *pdev, ...@@ -3417,9 +3426,9 @@ static int mv_pci_init_one(struct pci_dev *pdev,
if (rc) if (rc)
return rc; return rc;
/* Enable interrupts */ /* Enable message-switched interrupts, if requested */
if (msi && pci_enable_msi(pdev)) if (msi && pci_enable_msi(pdev) == 0)
pci_intx(pdev, 1); hpriv->hp_flags |= MV_HP_FLAG_MSI;
mv_dump_pci_cfg(pdev, 0x68); mv_dump_pci_cfg(pdev, 0x68);
mv_print_info(host); mv_print_info(host);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment