Skip to content

Commit d243bed

Browse files
Tirumalesh Chalamarlahtejun
authored andcommitted
ahci: Workaround for ThunderX Errata#22536
Due to Errata in ThunderX, HOST_IRQ_STAT should be cleared before leaving the interrupt handler. The patch attempts to satisfy the need. Changes from V2: - removed newfile - code is now under CONFIG_ARM64 Changes from V1: - Rebased on top of libata/for-4.6 - Moved ThunderX intr handler to new file tj: Minor adjustments to comments. Signed-off-by: Tirumalesh Chalamarla <tchalamarla@caviumnetworks.com> Signed-off-by: Tejun Heo <tj@kernel.org>
1 parent 4ee34ea commit d243bed

File tree

1 file changed

+43
-0
lines changed

1 file changed

+43
-0
lines changed

drivers/ata/ahci.c

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1331,6 +1331,44 @@ static inline void ahci_gtf_filter_workaround(struct ata_host *host)
13311331
{}
13321332
#endif
13331333

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+
13341372
/*
13351373
* ahci_init_msix() - optionally enable per-port MSI-X otherwise defer
13361374
* to single msi.
@@ -1566,6 +1604,11 @@ static int ahci_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
15661604
if (ahci_broken_devslp(pdev))
15671605
hpriv->flags |= AHCI_HFLAG_NO_DEVSLP;
15681606

1607+
#ifdef CONFIG_ARM64
1608+
if (pdev->vendor == 0x177d && pdev->device == 0xa01c)
1609+
hpriv->irq_handler = ahci_thunderx_irq_handler;
1610+
#endif
1611+
15691612
/* save initial config */
15701613
ahci_pci_save_initial_config(pdev, hpriv);
15711614

0 commit comments

Comments
 (0)