summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--drivers/ata/ahci.c9
-rw-r--r--drivers/ata/ahci.h1
2 files changed, 9 insertions, 1 deletions
diff --git a/drivers/ata/ahci.c b/drivers/ata/ahci.c
index e45b18ee04c3..f6b3e31f63cd 100644
--- a/drivers/ata/ahci.c
+++ b/drivers/ata/ahci.c
@@ -1164,7 +1164,7 @@ static inline void ahci_gtf_filter_workaround(struct ata_host *host)
#endif
static int ahci_init_interrupts(struct pci_dev *pdev, unsigned int n_ports,
- struct ahci_host_priv *hpriv)
+ struct ahci_host_priv *hpriv)
{
int nvec;
@@ -1189,6 +1189,13 @@ static int ahci_init_interrupts(struct pci_dev *pdev, unsigned int n_ports,
else if (nvec < 0)
goto intx;
+ /* fallback to single MSI mode if the controller enforced MRSM mode */
+ if (readl(hpriv->mmio + HOST_CTL) & HOST_MRSM) {
+ pci_disable_msi(pdev);
+ printk(KERN_INFO "ahci: MRSM is on, fallback to single MSI\n");
+ goto single_msi;
+ }
+
return nvec;
single_msi:
diff --git a/drivers/ata/ahci.h b/drivers/ata/ahci.h
index 51af275b3388..b5eb886da226 100644
--- a/drivers/ata/ahci.h
+++ b/drivers/ata/ahci.h
@@ -94,6 +94,7 @@ enum {
/* HOST_CTL bits */
HOST_RESET = (1 << 0), /* reset controller; self-clear */
HOST_IRQ_EN = (1 << 1), /* global IRQ enable */
+ HOST_MRSM = (1 << 2), /* MSI Revert to Single Message */
HOST_AHCI_EN = (1 << 31), /* AHCI enabled */
/* HOST_CAP bits */