diff options
Diffstat (limited to 'drivers/ata/ahci.c')
-rw-r--r-- | drivers/ata/ahci.c | 49 |
1 files changed, 49 insertions, 0 deletions
diff --git a/drivers/ata/ahci.c b/drivers/ata/ahci.c index 546a3692774f..146dc0b8ec61 100644 --- a/drivers/ata/ahci.c +++ b/drivers/ata/ahci.c @@ -367,15 +367,21 @@ static const struct pci_device_id ahci_pci_tbl[] = { { PCI_VDEVICE(INTEL, 0xa107), board_ahci }, /* Sunrise Point-H RAID */ { PCI_VDEVICE(INTEL, 0xa10f), board_ahci }, /* Sunrise Point-H RAID */ { PCI_VDEVICE(INTEL, 0x2822), board_ahci }, /* Lewisburg RAID*/ + { PCI_VDEVICE(INTEL, 0x2823), board_ahci }, /* Lewisburg AHCI*/ { PCI_VDEVICE(INTEL, 0x2826), board_ahci }, /* Lewisburg RAID*/ + { PCI_VDEVICE(INTEL, 0x2827), board_ahci }, /* Lewisburg RAID*/ { PCI_VDEVICE(INTEL, 0xa182), board_ahci }, /* Lewisburg AHCI*/ { PCI_VDEVICE(INTEL, 0xa184), board_ahci }, /* Lewisburg RAID*/ { PCI_VDEVICE(INTEL, 0xa186), board_ahci }, /* Lewisburg RAID*/ { PCI_VDEVICE(INTEL, 0xa18e), board_ahci }, /* Lewisburg RAID*/ + { PCI_VDEVICE(INTEL, 0xa1d2), board_ahci }, /* Lewisburg RAID*/ + { PCI_VDEVICE(INTEL, 0xa1d6), board_ahci }, /* Lewisburg RAID*/ { PCI_VDEVICE(INTEL, 0xa202), board_ahci }, /* Lewisburg AHCI*/ { PCI_VDEVICE(INTEL, 0xa204), board_ahci }, /* Lewisburg RAID*/ { PCI_VDEVICE(INTEL, 0xa206), board_ahci }, /* Lewisburg RAID*/ { PCI_VDEVICE(INTEL, 0xa20e), board_ahci }, /* Lewisburg RAID*/ + { PCI_VDEVICE(INTEL, 0xa252), board_ahci }, /* Lewisburg RAID*/ + { PCI_VDEVICE(INTEL, 0xa256), board_ahci }, /* Lewisburg RAID*/ /* JMicron 360/1/3/5/6, match class to avoid IDE function */ { PCI_VENDOR_ID_JMICRON, PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID, @@ -1325,6 +1331,44 @@ static inline void ahci_gtf_filter_workaround(struct ata_host *host) {} #endif +#ifdef CONFIG_ARM64 +/* + * Due to ERRATA#22536, ThunderX needs to handle HOST_IRQ_STAT differently. + * Workaround is to make sure all pending IRQs are served before leaving + * handler. + */ +static irqreturn_t ahci_thunderx_irq_handler(int irq, void *dev_instance) +{ + struct ata_host *host = dev_instance; + struct ahci_host_priv *hpriv; + unsigned int rc = 0; + void __iomem *mmio; + u32 irq_stat, irq_masked; + unsigned int handled = 1; + + VPRINTK("ENTER\n"); + hpriv = host->private_data; + mmio = hpriv->mmio; + irq_stat = readl(mmio + HOST_IRQ_STAT); + if (!irq_stat) + return IRQ_NONE; + + do { + irq_masked = irq_stat & hpriv->port_map; + spin_lock(&host->lock); + rc = ahci_handle_port_intr(host, irq_masked); + if (!rc) + handled = 0; + writel(irq_stat, mmio + HOST_IRQ_STAT); + irq_stat = readl(mmio + HOST_IRQ_STAT); + spin_unlock(&host->lock); + } while (irq_stat); + VPRINTK("EXIT\n"); + + return IRQ_RETVAL(handled); +} +#endif + /* * ahci_init_msix() - optionally enable per-port MSI-X otherwise defer * to single msi. @@ -1560,6 +1604,11 @@ static int ahci_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) if (ahci_broken_devslp(pdev)) hpriv->flags |= AHCI_HFLAG_NO_DEVSLP; +#ifdef CONFIG_ARM64 + if (pdev->vendor == 0x177d && pdev->device == 0xa01c) + hpriv->irq_handler = ahci_thunderx_irq_handler; +#endif + /* save initial config */ ahci_pci_save_initial_config(pdev, hpriv); |