aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/ata/libahci.c74
1 files changed, 61 insertions, 13 deletions
diff --git a/drivers/ata/libahci.c b/drivers/ata/libahci.c
index 97683e45ab04..3ce3d23e4f97 100644
--- a/drivers/ata/libahci.c
+++ b/drivers/ata/libahci.c
@@ -1778,15 +1778,16 @@ static void ahci_handle_port_interrupt(struct ata_port *ap,
1778 } 1778 }
1779} 1779}
1780 1780
1781static void ahci_port_intr(struct ata_port *ap) 1781static void ahci_update_intr_status(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;
1784 u32 status; 1785 u32 status;
1785 1786
1786 status = readl(port_mmio + PORT_IRQ_STAT); 1787 status = readl(port_mmio + PORT_IRQ_STAT);
1787 writel(status, port_mmio + PORT_IRQ_STAT); 1788 writel(status, port_mmio + PORT_IRQ_STAT);
1788 1789
1789 ahci_handle_port_interrupt(ap, port_mmio, status); 1790 atomic_or(status, &pp->intr_status);
1790} 1791}
1791 1792
1792static irqreturn_t ahci_port_thread_fn(int irq, void *dev_instance) 1793static irqreturn_t ahci_port_thread_fn(int irq, void *dev_instance)
@@ -1807,6 +1808,34 @@ static irqreturn_t ahci_port_thread_fn(int irq, void *dev_instance)
1807 return IRQ_HANDLED; 1808 return IRQ_HANDLED;
1808} 1809}
1809 1810
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
1810static irqreturn_t ahci_multi_irqs_intr(int irq, void *dev_instance) 1839static irqreturn_t ahci_multi_irqs_intr(int irq, void *dev_instance)
1811{ 1840{
1812 struct ata_port *ap = dev_instance; 1841 struct ata_port *ap = dev_instance;
@@ -1856,7 +1885,7 @@ static irqreturn_t ahci_single_irq_intr(int irq, void *dev_instance)
1856 1885
1857 ap = host->ports[i]; 1886 ap = host->ports[i];
1858 if (ap) { 1887 if (ap) {
1859 ahci_port_intr(ap); 1888 ahci_update_intr_status(ap);
1860 VPRINTK("port %u\n", i); 1889 VPRINTK("port %u\n", i);
1861 } else { 1890 } else {
1862 VPRINTK("port %u (no irq)\n", i); 1891 VPRINTK("port %u (no irq)\n", i);
@@ -1883,7 +1912,7 @@ static irqreturn_t ahci_single_irq_intr(int irq, void *dev_instance)
1883 1912
1884 VPRINTK("EXIT\n"); 1913 VPRINTK("EXIT\n");
1885 1914
1886 return IRQ_RETVAL(handled); 1915 return handled ? IRQ_WAKE_THREAD : IRQ_NONE;
1887} 1916}
1888 1917
1889unsigned int ahci_qc_issue(struct ata_queued_cmd *qc) 1918unsigned int ahci_qc_issue(struct ata_queued_cmd *qc)
@@ -2295,13 +2324,8 @@ static int ahci_port_start(struct ata_port *ap)
2295 */ 2324 */
2296 pp->intr_mask = DEF_PORT_IRQ; 2325 pp->intr_mask = DEF_PORT_IRQ;
2297 2326
2298 /* 2327 spin_lock_init(&pp->lock);
2299 * Switch to per-port locking in case each port has its own MSI vector. 2328 ap->lock = &pp->lock;
2300 */
2301 if ((hpriv->flags & AHCI_HFLAG_MULTI_MSI)) {
2302 spin_lock_init(&pp->lock);
2303 ap->lock = &pp->lock;
2304 }
2305 2329
2306 ap->private_data = pp; 2330 ap->private_data = pp;
2307 2331
@@ -2462,6 +2486,31 @@ out_free_irqs:
2462 return rc; 2486 return rc;
2463} 2487}
2464 2488
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
2465/** 2514/**
2466 * ahci_host_activate - start AHCI host, request IRQs and register it 2515 * ahci_host_activate - start AHCI host, request IRQs and register it
2467 * @host: target ATA host 2516 * @host: target ATA host
@@ -2487,8 +2536,7 @@ int ahci_host_activate(struct ata_host *host, int irq,
2487 if (hpriv->flags & AHCI_HFLAG_MULTI_MSI) 2536 if (hpriv->flags & AHCI_HFLAG_MULTI_MSI)
2488 rc = ahci_host_activate_multi_irqs(host, irq, sht); 2537 rc = ahci_host_activate_multi_irqs(host, irq, sht);
2489 else 2538 else
2490 rc = ata_host_activate(host, irq, ahci_single_irq_intr, 2539 rc = ahci_host_activate_single_irq(host, irq, sht);
2491 IRQF_SHARED, sht);
2492 return rc; 2540 return rc;
2493} 2541}
2494EXPORT_SYMBOL_GPL(ahci_host_activate); 2542EXPORT_SYMBOL_GPL(ahci_host_activate);