diff options
Diffstat (limited to 'drivers/ata/libahci.c')
-rw-r--r-- | drivers/ata/libahci.c | 78 |
1 files changed, 17 insertions, 61 deletions
diff --git a/drivers/ata/libahci.c b/drivers/ata/libahci.c index 5eb61c9e63da..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 | ||
1781 | static void ahci_update_intr_status(struct ata_port *ap) | 1781 | static 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 | ||
1793 | static irqreturn_t ahci_port_thread_fn(int irq, void *dev_instance) | 1792 | static 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 | ||
1811 | irqreturn_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 | |||
1839 | static irqreturn_t ahci_multi_irqs_intr(int irq, void *dev_instance) | 1810 | static 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; |
@@ -1875,6 +1846,8 @@ static irqreturn_t ahci_single_irq_intr(int irq, void *dev_instance) | |||
1875 | 1846 | ||
1876 | irq_masked = irq_stat & hpriv->port_map; | 1847 | irq_masked = irq_stat & hpriv->port_map; |
1877 | 1848 | ||
1849 | spin_lock(&host->lock); | ||
1850 | |||
1878 | for (i = 0; i < host->n_ports; i++) { | 1851 | for (i = 0; i < host->n_ports; i++) { |
1879 | struct ata_port *ap; | 1852 | struct ata_port *ap; |
1880 | 1853 | ||
@@ -1883,7 +1856,7 @@ static irqreturn_t ahci_single_irq_intr(int irq, void *dev_instance) | |||
1883 | 1856 | ||
1884 | ap = host->ports[i]; | 1857 | ap = host->ports[i]; |
1885 | if (ap) { | 1858 | if (ap) { |
1886 | ahci_update_intr_status(ap); | 1859 | ahci_port_intr(ap); |
1887 | VPRINTK("port %u\n", i); | 1860 | VPRINTK("port %u\n", i); |
1888 | } else { | 1861 | } else { |
1889 | VPRINTK("port %u (no irq)\n", i); | 1862 | VPRINTK("port %u (no irq)\n", i); |
@@ -1906,9 +1879,11 @@ static irqreturn_t ahci_single_irq_intr(int irq, void *dev_instance) | |||
1906 | */ | 1879 | */ |
1907 | writel(irq_stat, mmio + HOST_IRQ_STAT); | 1880 | writel(irq_stat, mmio + HOST_IRQ_STAT); |
1908 | 1881 | ||
1882 | spin_unlock(&host->lock); | ||
1883 | |||
1909 | VPRINTK("EXIT\n"); | 1884 | VPRINTK("EXIT\n"); |
1910 | 1885 | ||
1911 | return handled ? IRQ_WAKE_THREAD : IRQ_NONE; | 1886 | return IRQ_RETVAL(handled); |
1912 | } | 1887 | } |
1913 | 1888 | ||
1914 | unsigned int ahci_qc_issue(struct ata_queued_cmd *qc) | 1889 | unsigned int ahci_qc_issue(struct ata_queued_cmd *qc) |
@@ -2320,8 +2295,13 @@ static int ahci_port_start(struct ata_port *ap) | |||
2320 | */ | 2295 | */ |
2321 | pp->intr_mask = DEF_PORT_IRQ; | 2296 | pp->intr_mask = DEF_PORT_IRQ; |
2322 | 2297 | ||
2323 | spin_lock_init(&pp->lock); | 2298 | /* |
2324 | 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 | } | ||
2325 | 2305 | ||
2326 | ap->private_data = pp; | 2306 | ap->private_data = pp; |
2327 | 2307 | ||
@@ -2482,31 +2462,6 @@ out_free_irqs: | |||
2482 | return rc; | 2462 | return rc; |
2483 | } | 2463 | } |
2484 | 2464 | ||
2485 | static int ahci_host_activate_single_irq(struct ata_host *host, int irq, | ||
2486 | struct scsi_host_template *sht) | ||
2487 | { | ||
2488 | int i, rc; | ||
2489 | |||
2490 | rc = ata_host_start(host); | ||
2491 | if (rc) | ||
2492 | return rc; | ||
2493 | |||
2494 | rc = devm_request_threaded_irq(host->dev, irq, ahci_single_irq_intr, | ||
2495 | ahci_thread_fn, IRQF_SHARED, | ||
2496 | dev_driver_string(host->dev), host); | ||
2497 | if (rc) | ||
2498 | return rc; | ||
2499 | |||
2500 | for (i = 0; i < host->n_ports; i++) | ||
2501 | ata_port_desc(host->ports[i], "irq %d", irq); | ||
2502 | |||
2503 | rc = ata_host_register(host, sht); | ||
2504 | if (rc) | ||
2505 | devm_free_irq(host->dev, irq, host); | ||
2506 | |||
2507 | return rc; | ||
2508 | } | ||
2509 | |||
2510 | /** | 2465 | /** |
2511 | * ahci_host_activate - start AHCI host, request IRQs and register it | 2466 | * ahci_host_activate - start AHCI host, request IRQs and register it |
2512 | * @host: target ATA host | 2467 | * @host: target ATA host |
@@ -2532,7 +2487,8 @@ int ahci_host_activate(struct ata_host *host, int irq, | |||
2532 | if (hpriv->flags & AHCI_HFLAG_MULTI_MSI) | 2487 | if (hpriv->flags & AHCI_HFLAG_MULTI_MSI) |
2533 | rc = ahci_host_activate_multi_irqs(host, irq, sht); | 2488 | rc = ahci_host_activate_multi_irqs(host, irq, sht); |
2534 | else | 2489 | else |
2535 | rc = ahci_host_activate_single_irq(host, irq, sht); | 2490 | rc = ata_host_activate(host, irq, ahci_single_irq_intr, |
2491 | IRQF_SHARED, sht); | ||
2536 | return rc; | 2492 | return rc; |
2537 | } | 2493 | } |
2538 | EXPORT_SYMBOL_GPL(ahci_host_activate); | 2494 | EXPORT_SYMBOL_GPL(ahci_host_activate); |