diff options
author | Peter Daifuku <pdaifuku@nvidia.com> | 2014-01-10 15:57:28 -0800 |
---|---|---|
committer | Jay Agarwal <jagarwal@nvidia.com> | 2014-01-17 09:54:12 -0800 |
commit | 7908f31c3e7a5cfa9c053f89acc5691c6502e3a3 (patch) | |
tree | 9641a07dddab3832bc94b660bc3f42f23b6d4000 /drivers/pci/host | |
parent | bc5f5dc7d8652dd109dfa1838b1f7490e818e04e (diff) |
pcie: host: tegra: re-enable MSI after resume
Initialize core MSI data once and re-enable MSI
registers on resume, if MSI were enabled.
Bug 1363735
Change-Id: I3d3d7e21be121e38d5159302ec47aaff9dcf7525
Signed-off-by: Peter Daifuku <pdaifuku@nvidia.com>
Signed-off-by: Jay Agarwal <jagarwal@nvidia.com>
Reviewed-on: http://git-master/r/354470
Reviewed-by: Automatic_Commit_Validation_User
Reviewed-by: Venu Byravarasu <vbyravarasu@nvidia.com>
GVS: Gerrit_Virtual_Submit
Diffstat (limited to 'drivers/pci/host')
-rw-r--r-- | drivers/pci/host/pci-tegra.c | 65 |
1 files changed, 31 insertions, 34 deletions
diff --git a/drivers/pci/host/pci-tegra.c b/drivers/pci/host/pci-tegra.c index c8417a096cc9..fa0b70a0f4fc 100644 --- a/drivers/pci/host/pci-tegra.c +++ b/drivers/pci/host/pci-tegra.c @@ -293,7 +293,6 @@ static struct resource pcie_mem_space; static struct resource pcie_prefetch_mem_space; /* this flag enables features required either after boot or resume */ -/* also required to enable msi from host both after boot and resume */ static bool resume_path; /* used to avoid successive hotplug disconnect or connect */ static bool hotplug_event; @@ -1842,6 +1841,8 @@ static int tegra_pcie_suspend_noirq(struct device *dev) return tegra_pcie_power_off(); } +static bool tegra_pcie_enable_msi(bool); + static int tegra_pcie_resume_noirq(struct device *dev) { int ret = 0; @@ -1867,6 +1868,8 @@ static int tegra_pcie_resume_noirq(struct device *dev) tegra_pcie_enable_pads(true); tegra_pcie_enable_controller(); tegra_pcie_setup_translations(); + /* Set up MSI registers, if MSI have been enabled */ + tegra_pcie_enable_msi(true); tegra_pcie_check_ports(); if (!tegra_pcie.num_ports) { @@ -2033,37 +2036,38 @@ static irqreturn_t tegra_pcie_msi_isr(int irq, void *arg) return IRQ_HANDLED; } -static bool tegra_pcie_enable_msi(void) +static bool tegra_pcie_enable_msi(bool no_init) { - bool retval = false; u32 reg; - u32 msi_base = 0; - u32 msi_aligned = 0; + static u32 msi_base; PR_FUNC_LINE; - /* this only happens once. */ - if (resume_path) { - retval = true; - goto exit; - } - msi_map_init(); + if (!msi_base) { + /* if not already initialized and no_init, nothing to do */ + if (no_init) + return true; - /* enables MSI interrupts. */ - if (request_irq(INT_PCIE_MSI, tegra_pcie_msi_isr, - IRQF_SHARED, "PCIe-MSI", - tegra_pcie_msi_isr)) { + msi_map_init(); + + /* enables MSI interrupts. */ + if (request_irq(INT_PCIE_MSI, tegra_pcie_msi_isr, + IRQF_SHARED, "PCIe-MSI", tegra_pcie_msi_isr)) { pr_err("%s: Cannot register IRQ %u\n", - __func__, INT_PCIE_MSI); - goto exit; + __func__, INT_PCIE_MSI); + return false; + } + /* setup AFI/FPCI range */ + /* FIXME do this better! should be based on PAGE_SIZE */ + msi_base = __get_free_pages(GFP_KERNEL, 3); + if (!msi_base) { + pr_err("PCIE: Insufficient memory\n"); + return false; + } + msi_base = virt_to_phys((void *)msi_base); } - /* setup AFI/FPCI range */ - /* FIXME do this better! should be based on PAGE_SIZE */ - msi_base = __get_free_pages(GFP_KERNEL, 3); - msi_aligned = ((msi_base + ((1<<12) - 1)) & ~((1<<12) - 1)); - msi_aligned = virt_to_phys((void *)msi_aligned); - - afi_writel(msi_aligned>>8, AFI_MSI_FPCI_BAR_ST); - afi_writel(msi_aligned, AFI_MSI_AXI_BAR_ST); + + afi_writel(msi_base>>8, AFI_MSI_FPCI_BAR_ST); + afi_writel(msi_base, AFI_MSI_AXI_BAR_ST); /* this register is in 4K increments */ afi_writel(1, AFI_MSI_BAR_SZ); @@ -2084,14 +2088,7 @@ static bool tegra_pcie_enable_msi(void) set_irq_flags(INT_PCIE_MSI, IRQF_VALID); - resume_path = true; - retval = true; -exit: - if (!retval) { - if (msi_base) - free_pages(msi_base, 3); - } - return retval; + return true; } @@ -2103,7 +2100,7 @@ int arch_setup_msi_irq(struct pci_dev *pdev, struct msi_desc *desc) struct msi_map_entry *map_entry = NULL; PR_FUNC_LINE; - if (!tegra_pcie_enable_msi()) + if (!tegra_pcie_enable_msi(false)) goto exit; map_entry = msi_map_get(); |