aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTejun Heo <tj@kernel.org>2014-10-27 09:50:36 -0400
committerTejun Heo <tj@kernel.org>2014-10-27 12:02:05 -0400
commit7865f83fd2f23cbf3cd8ad0ddc2cef796f005aaf (patch)
treea268decde6f88ac899c55fc4812d9e4839688efe
parent03e83cbd34a4602bf0d750e5ff4bf8b7d0e066b2 (diff)
Revert "AHCI: Optimize single IRQ interrupt processing"
This reverts commit 18dcf433f3ded61eb140a55e7048ec2fef79e723. IRQF_ONESHOT was missing from the conversion causing screaming interrupts problems on some setups and LKP detected measureable drop in IO performance. It looks like we'll first need to drop the threaded IRQ handling first before splitting locking. Signed-off-by: Tejun Heo <tj@kernel.org> Cc: Alexander Gordeev <agordeev@redhat.com> Reported-by: kernel test robot <fengguang.wu@intel.com> Reported-by: Marc Zyngier <marc.zyngier@arm.com> Link: http://lkml.kernel.org/g/20141027021651.GF27038@yliu-dev.sh.intel.com Link: http://lkml.kernel.org/g/1414082970-20775-1-git-send-email-marc.zyngier@arm.com
-rw-r--r--drivers/ata/libahci.c74
1 files changed, 13 insertions, 61 deletions
diff --git a/drivers/ata/libahci.c b/drivers/ata/libahci.c
index 3ce3d23e4f97..97683e45ab04 100644
--- a/drivers/ata/libahci.c
+++ b/drivers/ata/libahci.c
@@ -1778,16 +1778,15 @@ static void ahci_handle_port_interrupt(struct ata_port *ap,
1778 } 1778 }
1779} 1779}
1780 1780
1781static void ahci_update_intr_status(struct ata_port *ap) 1781static void ahci_port_intr(struct ata_port *ap)
1782{ 1782{
1783 void __iomem *port_mmio = ahci_port_base(ap); 1783 void __iomem *port_mmio = ahci_port_base(ap);
1784 struct ahci_port_priv *pp = ap->private_data;
1785 u32 status; 1784 u32 status;
1786 1785
1787 status = readl(port_mmio + PORT_IRQ_STAT); 1786 status = readl(port_mmio + PORT_IRQ_STAT);
1788 writel(status, port_mmio + PORT_IRQ_STAT); 1787 writel(status, port_mmio + PORT_IRQ_STAT);
1789 1788
1790 atomic_or(status, &pp->intr_status); 1789 ahci_handle_port_interrupt(ap, port_mmio, status);
1791} 1790}
1792 1791
1793static irqreturn_t ahci_port_thread_fn(int irq, void *dev_instance) 1792static irqreturn_t ahci_port_thread_fn(int irq, void *dev_instance)
@@ -1808,34 +1807,6 @@ static irqreturn_t ahci_port_thread_fn(int irq, void *dev_instance)
1808 return IRQ_HANDLED; 1807 return IRQ_HANDLED;
1809} 1808}
1810 1809
1811irqreturn_t ahci_thread_fn(int irq, void *dev_instance)
1812{
1813 struct ata_host *host = dev_instance;
1814 struct ahci_host_priv *hpriv = host->private_data;
1815 u32 irq_masked = hpriv->port_map;
1816 unsigned int i;
1817
1818 for (i = 0; i < host->n_ports; i++) {
1819 struct ata_port *ap;
1820
1821 if (!(irq_masked & (1 << i)))
1822 continue;
1823
1824 ap = host->ports[i];
1825 if (ap) {
1826 ahci_port_thread_fn(irq, ap);
1827 VPRINTK("port %u\n", i);
1828 } else {
1829 VPRINTK("port %u (no irq)\n", i);
1830 if (ata_ratelimit())
1831 dev_warn(host->dev,
1832 "interrupt on disabled port %u\n", i);
1833 }
1834 }
1835
1836 return IRQ_HANDLED;
1837}
1838
1839static irqreturn_t ahci_multi_irqs_intr(int irq, void *dev_instance) 1810static irqreturn_t ahci_multi_irqs_intr(int irq, void *dev_instance)
1840{ 1811{
1841 struct ata_port *ap = dev_instance; 1812 struct ata_port *ap = dev_instance;
@@ -1885,7 +1856,7 @@ static irqreturn_t ahci_single_irq_intr(int irq, void *dev_instance)
1885 1856
1886 ap = host->ports[i]; 1857 ap = host->ports[i];
1887 if (ap) { 1858 if (ap) {
1888 ahci_update_intr_status(ap); 1859 ahci_port_intr(ap);
1889 VPRINTK("port %u\n", i); 1860 VPRINTK("port %u\n", i);
1890 } else { 1861 } else {
1891 VPRINTK("port %u (no irq)\n", i); 1862 VPRINTK("port %u (no irq)\n", i);
@@ -1912,7 +1883,7 @@ static irqreturn_t ahci_single_irq_intr(int irq, void *dev_instance)
1912 1883
1913 VPRINTK("EXIT\n"); 1884 VPRINTK("EXIT\n");
1914 1885
1915 return handled ? IRQ_WAKE_THREAD : IRQ_NONE; 1886 return IRQ_RETVAL(handled);
1916} 1887}
1917 1888
1918unsigned int ahci_qc_issue(struct ata_queued_cmd *qc) 1889unsigned int ahci_qc_issue(struct ata_queued_cmd *qc)
@@ -2324,8 +2295,13 @@ static int ahci_port_start(struct ata_port *ap)
2324 */ 2295 */
2325 pp->intr_mask = DEF_PORT_IRQ; 2296 pp->intr_mask = DEF_PORT_IRQ;
2326 2297
2327 spin_lock_init(&pp->lock); 2298 /*
2328 ap->lock = &pp->lock; 2299 * Switch to per-port locking in case each port has its own MSI vector.
2300 */
2301 if ((hpriv->flags & AHCI_HFLAG_MULTI_MSI)) {
2302 spin_lock_init(&pp->lock);
2303 ap->lock = &pp->lock;
2304 }
2329 2305
2330 ap->private_data = pp; 2306 ap->private_data = pp;
2331 2307
@@ -2486,31 +2462,6 @@ out_free_irqs:
2486 return rc; 2462 return rc;
2487} 2463}
2488 2464
2489static int ahci_host_activate_single_irq(struct ata_host *host, int irq,
2490 struct scsi_host_template *sht)
2491{
2492 int i, rc;
2493
2494 rc = ata_host_start(host);
2495 if (rc)
2496 return rc;
2497
2498 rc = devm_request_threaded_irq(host->dev, irq, ahci_single_irq_intr,
2499 ahci_thread_fn, IRQF_SHARED,
2500 dev_driver_string(host->dev), host);
2501 if (rc)
2502 return rc;
2503
2504 for (i = 0; i < host->n_ports; i++)
2505 ata_port_desc(host->ports[i], "irq %d", irq);
2506
2507 rc = ata_host_register(host, sht);
2508 if (rc)
2509 devm_free_irq(host->dev, irq, host);
2510
2511 return rc;
2512}
2513
2514/** 2465/**
2515 * ahci_host_activate - start AHCI host, request IRQs and register it 2466 * ahci_host_activate - start AHCI host, request IRQs and register it
2516 * @host: target ATA host 2467 * @host: target ATA host
@@ -2536,7 +2487,8 @@ int ahci_host_activate(struct ata_host *host, int irq,
2536 if (hpriv->flags & AHCI_HFLAG_MULTI_MSI) 2487 if (hpriv->flags & AHCI_HFLAG_MULTI_MSI)
2537 rc = ahci_host_activate_multi_irqs(host, irq, sht); 2488 rc = ahci_host_activate_multi_irqs(host, irq, sht);
2538 else 2489 else
2539 rc = ahci_host_activate_single_irq(host, irq, sht); 2490 rc = ata_host_activate(host, irq, ahci_single_irq_intr,
2491 IRQF_SHARED, sht);
2540 return rc; 2492 return rc;
2541} 2493}
2542EXPORT_SYMBOL_GPL(ahci_host_activate); 2494EXPORT_SYMBOL_GPL(ahci_host_activate);