diff options
| author | Mark Lord <liml@rtr.ca> | 2009-01-21 10:31:29 -0500 |
|---|---|---|
| committer | Jeff Garzik <jgarzik@redhat.com> | 2009-01-26 06:41:57 -0500 |
| commit | 6d3c30efc964fadf2e6270e6fceaeca3ce50027a (patch) | |
| tree | 555b60363b953a35836adf61ca0b5a4ca71e64a0 | |
| parent | 5d0fb2e730e2085021cf5c8b6d14983e92aea75b (diff) | |
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: Mark Lord <mlord@pobox.com>
Reviewed-by: Grant Grundler <grundler@google.com>
Signed-off-by: Jeff Garzik <jgarzik@redhat.com>
| -rw-r--r-- | drivers/ata/sata_mv.c | 21 |
1 files changed, 15 insertions, 6 deletions
diff --git a/drivers/ata/sata_mv.c b/drivers/ata/sata_mv.c index 9e9fb9594781..f2d8a020ea53 100644 --- a/drivers/ata/sata_mv.c +++ b/drivers/ata/sata_mv.c | |||
| @@ -33,8 +33,6 @@ | |||
| 33 | * | 33 | * |
| 34 | * --> ATAPI support (Marvell claims the 60xx/70xx chips can do it). | 34 | * --> ATAPI support (Marvell claims the 60xx/70xx chips can do it). |
| 35 | * | 35 | * |
| 36 | * --> Investigate problems with PCI Message Signalled Interrupts (MSI). | ||
| 37 | * | ||
| 38 | * --> Develop a low-power-consumption strategy, and implement it. | 36 | * --> Develop a low-power-consumption strategy, and implement it. |
| 39 | * | 37 | * |
| 40 | * --> [Experiment, low priority] Investigate interrupt coalescing. | 38 | * --> [Experiment, low priority] Investigate interrupt coalescing. |
| @@ -70,7 +68,7 @@ | |||
| 70 | #include <linux/libata.h> | 68 | #include <linux/libata.h> |
| 71 | 69 | ||
| 72 | #define DRV_NAME "sata_mv" | 70 | #define DRV_NAME "sata_mv" |
| 73 | #define DRV_VERSION "1.24" | 71 | #define DRV_VERSION "1.25" |
| 74 | 72 | ||
| 75 | enum { | 73 | enum { |
| 76 | /* BAR's are enumerated in terms of pci_resource_start() terms */ | 74 | /* 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 | struct ata_host *host = dev_instance; | 2197 | struct ata_host *host = dev_instance; |
| 2200 | struct mv_host_priv *hpriv = host->private_data; | 2198 | struct mv_host_priv *hpriv = host->private_data; |
| 2201 | unsigned int handled = 0; | 2199 | unsigned int handled = 0; |
| 2200 | int using_msi = hpriv->hp_flags & MV_HP_FLAG_MSI; | ||
| 2202 | u32 main_irq_cause, pending_irqs; | 2201 | u32 main_irq_cause, pending_irqs; |
| 2203 | 2202 | ||
| 2204 | spin_lock(&host->lock); | 2203 | spin_lock(&host->lock); |
| 2204 | |||
| 2205 | /* for MSI: block new interrupts while in here */ | ||
| 2206 | if (using_msi) | ||
| 2207 | writel(0, hpriv->main_irq_mask_addr); | ||
| 2208 | |||
| 2205 | main_irq_cause = readl(hpriv->main_irq_cause_addr); | 2209 | main_irq_cause = readl(hpriv->main_irq_cause_addr); |
| 2206 | pending_irqs = main_irq_cause & hpriv->main_irq_mask; | 2210 | pending_irqs = main_irq_cause & hpriv->main_irq_mask; |
| 2207 | /* | 2211 | /* |
| @@ -2215,6 +2219,11 @@ static irqreturn_t mv_interrupt(int irq, void *dev_instance) | |||
| 2215 | handled = mv_host_intr(host, pending_irqs); | 2219 | handled = mv_host_intr(host, pending_irqs); |
| 2216 | } | 2220 | } |
| 2217 | spin_unlock(&host->lock); | 2221 | spin_unlock(&host->lock); |
| 2222 | |||
| 2223 | /* for MSI: unmask; interrupt cause bits will retrigger now */ | ||
| 2224 | if (using_msi) | ||
| 2225 | writel(hpriv->main_irq_mask, hpriv->main_irq_mask_addr); | ||
| 2226 | |||
| 2218 | return IRQ_RETVAL(handled); | 2227 | return IRQ_RETVAL(handled); |
| 2219 | } | 2228 | } |
| 2220 | 2229 | ||
| @@ -3417,9 +3426,9 @@ static int mv_pci_init_one(struct pci_dev *pdev, | |||
| 3417 | if (rc) | 3426 | if (rc) |
| 3418 | return rc; | 3427 | return rc; |
| 3419 | 3428 | ||
| 3420 | /* Enable interrupts */ | 3429 | /* Enable message-switched interrupts, if requested */ |
| 3421 | if (msi && pci_enable_msi(pdev)) | 3430 | if (msi && pci_enable_msi(pdev) == 0) |
| 3422 | pci_intx(pdev, 1); | 3431 | hpriv->hp_flags |= MV_HP_FLAG_MSI; |
| 3423 | 3432 | ||
| 3424 | mv_dump_pci_cfg(pdev, 0x68); | 3433 | mv_dump_pci_cfg(pdev, 0x68); |
| 3425 | mv_print_info(host); | 3434 | mv_print_info(host); |
