aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/ata/ahci.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/ata/ahci.c')
-rw-r--r--drivers/ata/ahci.c35
1 files changed, 21 insertions, 14 deletions
diff --git a/drivers/ata/ahci.c b/drivers/ata/ahci.c
index 5a0bf8ed649b..71e15b73513d 100644
--- a/drivers/ata/ahci.c
+++ b/drivers/ata/ahci.c
@@ -1164,9 +1164,9 @@ static inline void ahci_gtf_filter_workaround(struct ata_host *host)
1164#endif 1164#endif
1165 1165
1166static int ahci_init_interrupts(struct pci_dev *pdev, unsigned int n_ports, 1166static int ahci_init_interrupts(struct pci_dev *pdev, unsigned int n_ports,
1167 struct ahci_host_priv *hpriv) 1167 struct ahci_host_priv *hpriv)
1168{ 1168{
1169 int nvec; 1169 int rc, nvec;
1170 1170
1171 if (hpriv->flags & AHCI_HFLAG_NO_MSI) 1171 if (hpriv->flags & AHCI_HFLAG_NO_MSI)
1172 goto intx; 1172 goto intx;
@@ -1183,12 +1183,19 @@ static int ahci_init_interrupts(struct pci_dev *pdev, unsigned int n_ports,
1183 if (nvec < n_ports) 1183 if (nvec < n_ports)
1184 goto single_msi; 1184 goto single_msi;
1185 1185
1186 nvec = pci_enable_msi_range(pdev, nvec, nvec); 1186 rc = pci_enable_msi_exact(pdev, nvec);
1187 if (nvec == -ENOSPC) 1187 if (rc == -ENOSPC)
1188 goto single_msi; 1188 goto single_msi;
1189 else if (nvec < 0) 1189 else if (rc < 0)
1190 goto intx; 1190 goto intx;
1191 1191
1192 /* fallback to single MSI mode if the controller enforced MRSM mode */
1193 if (readl(hpriv->mmio + HOST_CTL) & HOST_MRSM) {
1194 pci_disable_msi(pdev);
1195 printk(KERN_INFO "ahci: MRSM is on, fallback to single MSI\n");
1196 goto single_msi;
1197 }
1198
1192 return nvec; 1199 return nvec;
1193 1200
1194single_msi: 1201single_msi:
@@ -1232,18 +1239,18 @@ int ahci_host_activate(struct ata_host *host, int irq, unsigned int n_msis)
1232 return rc; 1239 return rc;
1233 1240
1234 for (i = 0; i < host->n_ports; i++) { 1241 for (i = 0; i < host->n_ports; i++) {
1235 const char* desc;
1236 struct ahci_port_priv *pp = host->ports[i]->private_data; 1242 struct ahci_port_priv *pp = host->ports[i]->private_data;
1237 1243
1238 /* pp is NULL for dummy ports */ 1244 /* Do not receive interrupts sent by dummy ports */
1239 if (pp) 1245 if (!pp) {
1240 desc = pp->irq_desc; 1246 disable_irq(irq + i);
1241 else 1247 continue;
1242 desc = dev_driver_string(host->dev); 1248 }
1243 1249
1244 rc = devm_request_threaded_irq(host->dev, 1250 rc = devm_request_threaded_irq(host->dev, irq + i,
1245 irq + i, ahci_hw_interrupt, ahci_thread_fn, IRQF_SHARED, 1251 ahci_hw_interrupt,
1246 desc, host->ports[i]); 1252 ahci_thread_fn, IRQF_SHARED,
1253 pp->irq_desc, host->ports[i]);
1247 if (rc) 1254 if (rc)
1248 goto out_free_irqs; 1255 goto out_free_irqs;
1249 } 1256 }