diff options
| -rw-r--r-- | drivers/ata/libahci.c | 74 |
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 | ||
| 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; |
| @@ -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 | ||
| 1918 | unsigned int ahci_qc_issue(struct ata_queued_cmd *qc) | 1889 | unsigned 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 | ||
| 2489 | static 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 | } |
| 2542 | EXPORT_SYMBOL_GPL(ahci_host_activate); | 2494 | EXPORT_SYMBOL_GPL(ahci_host_activate); |
