aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/ata/libahci.c
diff options
context:
space:
mode:
authorAlexander Gordeev <agordeev@redhat.com>2014-09-29 12:26:01 -0400
committerTejun Heo <tj@kernel.org>2014-10-06 11:43:36 -0400
commit227dfb4dbf109596d76a9b842856c4ff68e4efb2 (patch)
tree21d347c6ee2f4d53fffd158bab63acecd23d9a39 /drivers/ata/libahci.c
parent5ee1cfd975518bc9cdcd79e0b76552b5ae5c8c1e (diff)
AHCI: Do not read HOST_IRQ_STAT reg in multi-MSI mode
As described in AHCI v1.0 specification chapter 10.6.2.2 "Multiple MSI Based Messages" generation of interrupts is not controlled through the HOST_IRQ_STAT register. Considering MMIO access is expensive remove unnecessary reading and writing of HOST_IRQ_STAT register. Further, serializing access to the host data is no longer needed and the interrupt service routine can avoid competing on the host lock. Signed-off-by: Alexander Gordeev <agordeev@redhat.com> Suggested-by: "Jiang, Dave" <dave.jiang@intel.com> Signed-off-by: Tejun Heo <tj@kernel.org> Cc: "Jiang, Dave" <dave.jiang@intel.com> Cc: linux-ide@vger.kernel.org
Diffstat (limited to 'drivers/ata/libahci.c')
-rw-r--r--drivers/ata/libahci.c67
1 files changed, 8 insertions, 59 deletions
diff --git a/drivers/ata/libahci.c b/drivers/ata/libahci.c
index 48175e5bd001..97683e45ab04 100644
--- a/drivers/ata/libahci.c
+++ b/drivers/ata/libahci.c
@@ -1794,14 +1794,11 @@ static irqreturn_t ahci_port_thread_fn(int irq, void *dev_instance)
1794 struct ata_port *ap = dev_instance; 1794 struct ata_port *ap = dev_instance;
1795 struct ahci_port_priv *pp = ap->private_data; 1795 struct ahci_port_priv *pp = ap->private_data;
1796 void __iomem *port_mmio = ahci_port_base(ap); 1796 void __iomem *port_mmio = ahci_port_base(ap);
1797 unsigned long flags;
1798 u32 status; 1797 u32 status;
1799 1798
1800 spin_lock_irqsave(&ap->host->lock, flags); 1799 status = atomic_xchg(&pp->intr_status, 0);
1801 status = pp->intr_status; 1800 if (!status)
1802 if (status) 1801 return IRQ_NONE;
1803 pp->intr_status = 0;
1804 spin_unlock_irqrestore(&ap->host->lock, flags);
1805 1802
1806 spin_lock_bh(ap->lock); 1803 spin_lock_bh(ap->lock);
1807 ahci_handle_port_interrupt(ap, port_mmio, status); 1804 ahci_handle_port_interrupt(ap, port_mmio, status);
@@ -1810,67 +1807,19 @@ static irqreturn_t ahci_port_thread_fn(int irq, void *dev_instance)
1810 return IRQ_HANDLED; 1807 return IRQ_HANDLED;
1811} 1808}
1812 1809
1813static void ahci_update_intr_status(struct ata_port *ap) 1810static irqreturn_t ahci_multi_irqs_intr(int irq, void *dev_instance)
1814{ 1811{
1812 struct ata_port *ap = dev_instance;
1815 void __iomem *port_mmio = ahci_port_base(ap); 1813 void __iomem *port_mmio = ahci_port_base(ap);
1816 struct ahci_port_priv *pp = ap->private_data; 1814 struct ahci_port_priv *pp = ap->private_data;
1817 u32 status; 1815 u32 status;
1818 1816
1819 status = readl(port_mmio + PORT_IRQ_STAT);
1820 writel(status, port_mmio + PORT_IRQ_STAT);
1821
1822 pp->intr_status |= status;
1823}
1824
1825static irqreturn_t ahci_multi_irqs_intr(int irq, void *dev_instance)
1826{
1827 struct ata_port *ap_this = dev_instance;
1828 struct ahci_port_priv *pp = ap_this->private_data;
1829 struct ata_host *host = ap_this->host;
1830 struct ahci_host_priv *hpriv = host->private_data;
1831 void __iomem *mmio = hpriv->mmio;
1832 unsigned int i;
1833 u32 irq_stat, irq_masked;
1834
1835 VPRINTK("ENTER\n"); 1817 VPRINTK("ENTER\n");
1836 1818
1837 spin_lock(&host->lock); 1819 status = readl(port_mmio + PORT_IRQ_STAT);
1838 1820 writel(status, port_mmio + PORT_IRQ_STAT);
1839 irq_stat = readl(mmio + HOST_IRQ_STAT);
1840
1841 if (!irq_stat) {
1842 u32 status = pp->intr_status;
1843
1844 spin_unlock(&host->lock);
1845
1846 VPRINTK("EXIT\n");
1847
1848 return status ? IRQ_WAKE_THREAD : IRQ_NONE;
1849 }
1850
1851 irq_masked = irq_stat & hpriv->port_map;
1852
1853 for (i = 0; i < host->n_ports; i++) {
1854 struct ata_port *ap;
1855
1856 if (!(irq_masked & (1 << i)))
1857 continue;
1858
1859 ap = host->ports[i];
1860 if (ap) {
1861 ahci_update_intr_status(ap);
1862 VPRINTK("port %u\n", i);
1863 } else {
1864 VPRINTK("port %u (no irq)\n", i);
1865 if (ata_ratelimit())
1866 dev_warn(host->dev,
1867 "interrupt on disabled port %u\n", i);
1868 }
1869 }
1870
1871 writel(irq_stat, mmio + HOST_IRQ_STAT);
1872 1821
1873 spin_unlock(&host->lock); 1822 atomic_or(status, &pp->intr_status);
1874 1823
1875 VPRINTK("EXIT\n"); 1824 VPRINTK("EXIT\n");
1876 1825