Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

ahci: switch from 'threaded' to 'hardirq' interrupt handling

For high frequency I/O the overhead of threaded interrupts impacts
performance. A quick out-of-the-box test (i.e. no affinity tuning)
shows ~10% random read performance at ~20% less cpu. The cpu wins
appear to be from reduced lock contention.

Signed-off-by: Dan Williams <dan.j.williams@intel.com>
Signed-off-by: Tejun Heo <tj@kernel.org>

authored by

Dan Williams and committed by
Tejun Heo
a6b7fb76 d684a90d

+8 -26
+8 -26
drivers/ata/libahci.c
··· 1796 1796 ahci_handle_port_interrupt(ap, port_mmio, status); 1797 1797 } 1798 1798 1799 - static irqreturn_t ahci_port_thread_fn(int irq, void *dev_instance) 1800 - { 1801 - struct ata_port *ap = dev_instance; 1802 - struct ahci_port_priv *pp = ap->private_data; 1803 - void __iomem *port_mmio = ahci_port_base(ap); 1804 - u32 status; 1805 - 1806 - status = atomic_xchg(&pp->intr_status, 0); 1807 - if (!status) 1808 - return IRQ_NONE; 1809 - 1810 - spin_lock_bh(ap->lock); 1811 - ahci_handle_port_interrupt(ap, port_mmio, status); 1812 - spin_unlock_bh(ap->lock); 1813 - 1814 - return IRQ_HANDLED; 1815 - } 1816 - 1817 - static irqreturn_t ahci_multi_irqs_intr(int irq, void *dev_instance) 1799 + static irqreturn_t ahci_multi_irqs_intr_hard(int irq, void *dev_instance) 1818 1800 { 1819 1801 struct ata_port *ap = dev_instance; 1820 1802 void __iomem *port_mmio = ahci_port_base(ap); 1821 - struct ahci_port_priv *pp = ap->private_data; 1822 1803 u32 status; 1823 1804 1824 1805 VPRINTK("ENTER\n"); ··· 1807 1826 status = readl(port_mmio + PORT_IRQ_STAT); 1808 1827 writel(status, port_mmio + PORT_IRQ_STAT); 1809 1828 1810 - atomic_or(status, &pp->intr_status); 1829 + spin_lock(ap->lock); 1830 + ahci_handle_port_interrupt(ap, port_mmio, status); 1831 + spin_unlock(ap->lock); 1811 1832 1812 1833 VPRINTK("EXIT\n"); 1813 1834 1814 - return IRQ_WAKE_THREAD; 1835 + return IRQ_HANDLED; 1815 1836 } 1816 1837 1817 1838 static u32 ahci_handle_port_intr(struct ata_host *host, u32 irq_masked) ··· 2482 2499 continue; 2483 2500 } 2484 2501 2485 - rc = devm_request_threaded_irq(host->dev, irq, 2486 - ahci_multi_irqs_intr, 2487 - ahci_port_thread_fn, 0, 2488 - pp->irq_desc, host->ports[i]); 2502 + rc = devm_request_irq(host->dev, irq, ahci_multi_irqs_intr_hard, 2503 + 0, pp->irq_desc, host->ports[i]); 2504 + 2489 2505 if (rc) 2490 2506 return rc; 2491 2507 ata_port_desc(host->ports[i], "irq %d", irq);