diff options
Diffstat (limited to 'drivers/ata/ahci.c')
| -rw-r--r-- | drivers/ata/ahci.c | 35 |
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 | ||
| 1166 | static int ahci_init_interrupts(struct pci_dev *pdev, unsigned int n_ports, | 1166 | static 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 | ||
| 1194 | single_msi: | 1201 | single_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 | } |
