diff options
author | Jay Agarwal <jagarwal@nvidia.com> | 2012-07-02 19:23:47 +0530 |
---|---|---|
committer | Simone Willett <swillett@nvidia.com> | 2012-07-03 15:10:24 -0700 |
commit | 01ced1b7d14dc3711fa1fa394dd5190014f0d8d6 (patch) | |
tree | d4afcdcb4244ac471c2f2e0ae4a81bc7e3e5cbbb /arch | |
parent | 2cc337abc18dc992e736a3c663366e980021f806 (diff) |
arm: tegra: pcie: Resolve L4T ethernet failure
1. Removed the stop/add pci devices after rescan to
avoid panic in 2nd time suspend for L4T.
2. Moved the setting irq code before adding devices
to avoid probe failure for usb3.
Bug 959642
Bug 946385
Bug 1009086
Change-Id: Ia425a4e11667f6f2f110eb68d63c8fb229486c21
Signed-off-by: Jay Agarwal <jagarwal@nvidia.com>
Reviewed-on: http://git-master/r/112959
Reviewed-by: Automatic_Commit_Validation_User
Reviewed-by: Bharat Nihalani <bnihalani@nvidia.com>
Diffstat (limited to 'arch')
-rw-r--r-- | arch/arm/mach-tegra/pcie.c | 52 |
1 files changed, 35 insertions, 17 deletions
diff --git a/arch/arm/mach-tegra/pcie.c b/arch/arm/mach-tegra/pcie.c index 13383af20ed4..ec386a51721c 100644 --- a/arch/arm/mach-tegra/pcie.c +++ b/arch/arm/mach-tegra/pcie.c @@ -1333,11 +1333,28 @@ static int tegra_pcie_suspend(struct device *dev) return tegra_pcie_power_off(); } +static void tegra_pcie_set_irq(struct pci_bus *bus) +{ + struct pci_bus *b; + struct pci_dev *pdev; + + list_for_each_entry(pdev, &bus->devices, bus_list) { + b = pdev->subordinate; + if (!b) { + pdev->irq = tegra_pcie_map_irq(pdev,0,0); + pci_write_config_byte(pdev, PCI_INTERRUPT_LINE, pdev->irq); + continue; + } + tegra_pcie_set_irq(b); + pdev->irq = tegra_pcie_map_irq(pdev,0,0); + pci_write_config_byte(pdev, PCI_INTERRUPT_LINE, pdev->irq); + } +} + static int tegra_pcie_resume(struct device *dev) { int ret = 0; - struct pci_bus *b = NULL; - struct pci_dev *pdev = NULL; + struct pci_bus *bus = NULL; int port, rp_offset = 0; int ctrl_offset = AFI_PEX0_CTRL; @@ -1361,23 +1378,24 @@ static int tegra_pcie_resume(struct device *dev) } tegra_pcie_hotplug_init(); - while ((b = pci_find_next_bus(b)) != NULL) - pci_rescan_bus(b); - - /* Update irq line register since it is not done while scan */ - for_each_pci_dev(pdev) { - pdev->irq = tegra_pcie_map_irq(pdev,0,0); - pci_write_config_byte(pdev, PCI_INTERRUPT_LINE, pdev->irq); + while ((bus = pci_find_next_bus(bus)) != NULL) { + struct pci_dev *dev; + + pci_scan_child_bus(bus); + + list_for_each_entry(dev, &bus->devices, bus_list) + if (dev->hdr_type == PCI_HEADER_TYPE_BRIDGE || + dev->hdr_type == PCI_HEADER_TYPE_CARDBUS) + if (dev->subordinate) + pci_bus_size_bridges(dev->subordinate); + + /* set irq for all devices */ + tegra_pcie_set_irq(bus); + pci_bus_assign_resources(bus); + pci_enable_bridges(bus); + pci_bus_add_devices(bus); } - /* probe the devices again after having correct value of irq as above */ - pdev = NULL; - for_each_pci_dev(pdev) - pci_stop_bus_device(pdev); - b = NULL; - while ((b = pci_find_next_bus(b)) != NULL) - pci_bus_add_devices(b); - return ret; } #endif |