diff options
author | Jay Agarwal <jagarwal@nvidia.com> | 2013-12-31 20:22:14 +0530 |
---|---|---|
committer | Jay Agarwal <jagarwal@nvidia.com> | 2014-01-28 04:29:06 -0800 |
commit | 476e24e965a25ab2f7fe816383d67901a48a260a (patch) | |
tree | 5719eeacd7f03241d44b7f0f91ba216e1732da35 /drivers/pci/host/pci-tegra.c | |
parent | 86ef5c1bb65da6127fd0bacd5a12560f2914e56f (diff) |
pcie: host: tegra: Fix hotplug functionality
1. Avoid removing controller shutdown in detach
and init sequence in attach.
2. Instead, remove all data structures in detach
and recreate them in attach.
3. Also hide AER capability in detach to avoid AER
spews in log and unhide it attach.
Bug 1446334
Change-Id: Ic76f227e24d249d2374b700980697850a1e5303f
Signed-off-by: Jay Agarwal <jagarwal@nvidia.com>
Reviewed-on: http://git-master/r/351039
Reviewed-by: Automatic_Commit_Validation_User
Reviewed-by: Venu Byravarasu <vbyravarasu@nvidia.com>
Diffstat (limited to 'drivers/pci/host/pci-tegra.c')
-rw-r--r-- | drivers/pci/host/pci-tegra.c | 67 |
1 files changed, 40 insertions, 27 deletions
diff --git a/drivers/pci/host/pci-tegra.c b/drivers/pci/host/pci-tegra.c index 444b3ecd7a98..f651015d504c 100644 --- a/drivers/pci/host/pci-tegra.c +++ b/drivers/pci/host/pci-tegra.c @@ -205,8 +205,6 @@ #define NV_PCIE2_RP_ECTL_1_R2 0x00000FD8 #define PCIE2_RP_ECTL_1_R2_TX_DRV_CNTL_1C (0x3 << 28) -#define BOARD_PM359 0x0167 -#define BOARD_PM358 0x0166 /* * AXI address map for the PCIe aperture , defines 1GB in the AXI @@ -460,7 +458,6 @@ int tegra_pcie_read_conf(struct pci_bus *bus, unsigned int devfn, *val = 0xffffffff; return PCIBIOS_DEVICE_NOT_FOUND; } - addr = pp->base + (where & ~0x3); } else { addr = tegra_pcie_bus_map(bus->number); @@ -646,10 +643,6 @@ static struct hw_pci __initdata tegra_pcie_hw = { .map_irq = tegra_pcie_map_irq, }; -#ifdef CONFIG_PM -static int tegra_pcie_suspend_noirq(struct device *dev); -static int tegra_pcie_resume_noirq(struct device *dev); - #ifdef HOTPLUG_ON_SYSTEM_BOOT /* It enumerates the devices when dock is connected after system boot */ /* this is similar to pcibios_init_hw in bios32.c */ @@ -691,41 +684,63 @@ static void __init tegra_pcie_hotplug_init(void) is_dock_conn_at_boot = true; } #endif -#endif + +static void tegra_pcie_enable_aer(int index, bool enable) +{ + unsigned int data; + + PR_FUNC_LINE; + data = rp_readl(NV_PCIE2_RP_VEND_CTL1, index); + if (enable) + data |= PCIE2_RP_VEND_CTL1_ERPT; + else + data &= ~PCIE2_RP_VEND_CTL1_ERPT; + rp_writel(data, NV_PCIE2_RP_VEND_CTL1, index); +} + static int tegra_pcie_attach(void) { - int err = 0; + struct pci_bus *bus = NULL; + PR_FUNC_LINE; if (!hotplug_event) - return err; -#ifdef CONFIG_PM - err = tegra_pcie_resume_noirq(NULL); -#endif + return 0; + + /* rescan and recreate all pcie data structures */ + while ((bus = pci_find_next_bus(bus)) != NULL) + pci_rescan_bus(bus); + /* unhide AER capability */ + tegra_pcie_enable_aer(0, true); + hotplug_event = false; - return err; + return 0; } static int tegra_pcie_detach(void) { - int err = 0; + struct pci_dev *pdev = NULL; + PR_FUNC_LINE; if (hotplug_event) - return err; -#ifdef CONFIG_PM - err = tegra_pcie_suspend_noirq(NULL); -#endif + return 0; hotplug_event = true; - return err; + + /* hide AER capability to avoid log spew */ + tegra_pcie_enable_aer(0, false); + /* remove all pcie data structures */ + for_each_pci_dev(pdev) { + pci_stop_and_remove_bus_device(pdev); + break; + } + return 0; } static void tegra_pcie_prsnt_map_override(int index, bool prsnt) { unsigned int data; - if (hotplug_event) - return; - /* currently only hotplug on root port 0 supported */ PR_FUNC_LINE; + /* currently only hotplug on root port 0 supported */ data = rp_readl(NV_PCIE2_RP_PRIV_MISC, index); data &= ~PCIE2_RP_PRIV_MISC_PRSNT_MAP_EP_ABSNT; if (prsnt) @@ -1433,9 +1448,7 @@ static void tegra_pcie_enable_rp_features(int index) rp_writel(data, NV_PCIE2_RP_VEND_XP_BIST, index); /* unhide AER capability */ - data = rp_readl(NV_PCIE2_RP_VEND_CTL1, index); - data |= PCIE2_RP_VEND_CTL1_ERPT; - rp_writel(data, NV_PCIE2_RP_VEND_CTL1, index); + tegra_pcie_enable_aer(index, true); tegra_pcie_apply_sw_war(index, false); } @@ -1953,7 +1966,7 @@ static int __init tegra_pcie_init_driver(void) static void __exit_refok tegra_pcie_exit_driver(void) { if (tegra_platform_is_linsim() || tegra_platform_is_qt()) - return 0; + return; platform_driver_unregister(&tegra_pcie_driver); } |