summaryrefslogtreecommitdiff
path: root/arch/arm/mach-tegra/pcie.c
diff options
context:
space:
mode:
authorJay Agarwal <jagarwal@nvidia.com>2012-07-02 19:23:47 +0530
committerSimone Willett <swillett@nvidia.com>2012-07-03 15:10:24 -0700
commit01ced1b7d14dc3711fa1fa394dd5190014f0d8d6 (patch)
treed4afcdcb4244ac471c2f2e0ae4a81bc7e3e5cbbb /arch/arm/mach-tegra/pcie.c
parent2cc337abc18dc992e736a3c663366e980021f806 (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/arm/mach-tegra/pcie.c')
-rw-r--r--arch/arm/mach-tegra/pcie.c52
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