diff options
| -rw-r--r-- | drivers/ata/ahci.c | 43 |
1 files changed, 43 insertions, 0 deletions
diff --git a/drivers/ata/ahci.c b/drivers/ata/ahci.c index b6263b3996ab..146dc0b8ec61 100644 --- a/drivers/ata/ahci.c +++ b/drivers/ata/ahci.c | |||
| @@ -1331,6 +1331,44 @@ static inline void ahci_gtf_filter_workaround(struct ata_host *host) | |||
| 1331 | {} | 1331 | {} |
| 1332 | #endif | 1332 | #endif |
| 1333 | 1333 | ||
| 1334 | #ifdef CONFIG_ARM64 | ||
| 1335 | /* | ||
| 1336 | * Due to ERRATA#22536, ThunderX needs to handle HOST_IRQ_STAT differently. | ||
| 1337 | * Workaround is to make sure all pending IRQs are served before leaving | ||
| 1338 | * handler. | ||
| 1339 | */ | ||
| 1340 | static irqreturn_t ahci_thunderx_irq_handler(int irq, void *dev_instance) | ||
| 1341 | { | ||
| 1342 | struct ata_host *host = dev_instance; | ||
| 1343 | struct ahci_host_priv *hpriv; | ||
| 1344 | unsigned int rc = 0; | ||
| 1345 | void __iomem *mmio; | ||
| 1346 | u32 irq_stat, irq_masked; | ||
| 1347 | unsigned int handled = 1; | ||
| 1348 | |||
| 1349 | VPRINTK("ENTER\n"); | ||
| 1350 | hpriv = host->private_data; | ||
| 1351 | mmio = hpriv->mmio; | ||
| 1352 | irq_stat = readl(mmio + HOST_IRQ_STAT); | ||
| 1353 | if (!irq_stat) | ||
| 1354 | return IRQ_NONE; | ||
| 1355 | |||
| 1356 | do { | ||
| 1357 | irq_masked = irq_stat & hpriv->port_map; | ||
| 1358 | spin_lock(&host->lock); | ||
| 1359 | rc = ahci_handle_port_intr(host, irq_masked); | ||
| 1360 | if (!rc) | ||
| 1361 | handled = 0; | ||
| 1362 | writel(irq_stat, mmio + HOST_IRQ_STAT); | ||
| 1363 | irq_stat = readl(mmio + HOST_IRQ_STAT); | ||
| 1364 | spin_unlock(&host->lock); | ||
| 1365 | } while (irq_stat); | ||
| 1366 | VPRINTK("EXIT\n"); | ||
| 1367 | |||
| 1368 | return IRQ_RETVAL(handled); | ||
| 1369 | } | ||
| 1370 | #endif | ||
| 1371 | |||
| 1334 | /* | 1372 | /* |
| 1335 | * ahci_init_msix() - optionally enable per-port MSI-X otherwise defer | 1373 | * ahci_init_msix() - optionally enable per-port MSI-X otherwise defer |
| 1336 | * to single msi. | 1374 | * to single msi. |
| @@ -1566,6 +1604,11 @@ static int ahci_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) | |||
| 1566 | if (ahci_broken_devslp(pdev)) | 1604 | if (ahci_broken_devslp(pdev)) |
| 1567 | hpriv->flags |= AHCI_HFLAG_NO_DEVSLP; | 1605 | hpriv->flags |= AHCI_HFLAG_NO_DEVSLP; |
| 1568 | 1606 | ||
| 1607 | #ifdef CONFIG_ARM64 | ||
| 1608 | if (pdev->vendor == 0x177d && pdev->device == 0xa01c) | ||
| 1609 | hpriv->irq_handler = ahci_thunderx_irq_handler; | ||
| 1610 | #endif | ||
| 1611 | |||
| 1569 | /* save initial config */ | 1612 | /* save initial config */ |
| 1570 | ahci_pci_save_initial_config(pdev, hpriv); | 1613 | ahci_pci_save_initial_config(pdev, hpriv); |
| 1571 | 1614 | ||
