diff options
Diffstat (limited to 'arch/mips/pci/pci.c')
-rw-r--r-- | arch/mips/pci/pci.c | 80 |
1 files changed, 53 insertions, 27 deletions
diff --git a/arch/mips/pci/pci.c b/arch/mips/pci/pci.c index c7fe6ec621e6..a377e9d2d029 100644 --- a/arch/mips/pci/pci.c +++ b/arch/mips/pci/pci.c | |||
@@ -34,6 +34,8 @@ static struct pci_controller *hose_head, **hose_tail = &hose_head; | |||
34 | unsigned long PCIBIOS_MIN_IO = 0x0000; | 34 | unsigned long PCIBIOS_MIN_IO = 0x0000; |
35 | unsigned long PCIBIOS_MIN_MEM = 0; | 35 | unsigned long PCIBIOS_MIN_MEM = 0; |
36 | 36 | ||
37 | static int pci_initialized; | ||
38 | |||
37 | /* | 39 | /* |
38 | * We need to avoid collisions with `mirrored' VGA ports | 40 | * We need to avoid collisions with `mirrored' VGA ports |
39 | * and other strange ISA hardware, so we always want the | 41 | * and other strange ISA hardware, so we always want the |
@@ -74,6 +76,42 @@ pcibios_align_resource(void *data, struct resource *res, | |||
74 | res->start = start; | 76 | res->start = start; |
75 | } | 77 | } |
76 | 78 | ||
79 | static void __devinit pcibios_scanbus(struct pci_controller *hose) | ||
80 | { | ||
81 | static int next_busno; | ||
82 | static int need_domain_info; | ||
83 | struct pci_bus *bus; | ||
84 | |||
85 | if (!hose->iommu) | ||
86 | PCI_DMA_BUS_IS_PHYS = 1; | ||
87 | |||
88 | if (hose->get_busno && pci_probe_only) | ||
89 | next_busno = (*hose->get_busno)(); | ||
90 | |||
91 | bus = pci_scan_bus(next_busno, hose->pci_ops, hose); | ||
92 | hose->bus = bus; | ||
93 | |||
94 | need_domain_info = need_domain_info || hose->index; | ||
95 | hose->need_domain_info = need_domain_info; | ||
96 | if (bus) { | ||
97 | next_busno = bus->subordinate + 1; | ||
98 | /* Don't allow 8-bit bus number overflow inside the hose - | ||
99 | reserve some space for bridges. */ | ||
100 | if (next_busno > 224) { | ||
101 | next_busno = 0; | ||
102 | need_domain_info = 1; | ||
103 | } | ||
104 | |||
105 | if (!pci_probe_only) { | ||
106 | pci_bus_size_bridges(bus); | ||
107 | pci_bus_assign_resources(bus); | ||
108 | pci_enable_bridges(bus); | ||
109 | } | ||
110 | } | ||
111 | } | ||
112 | |||
113 | static DEFINE_MUTEX(pci_scan_mutex); | ||
114 | |||
77 | void __devinit register_pci_controller(struct pci_controller *hose) | 115 | void __devinit register_pci_controller(struct pci_controller *hose) |
78 | { | 116 | { |
79 | if (request_resource(&iomem_resource, hose->mem_resource) < 0) | 117 | if (request_resource(&iomem_resource, hose->mem_resource) < 0) |
@@ -93,6 +131,17 @@ void __devinit register_pci_controller(struct pci_controller *hose) | |||
93 | printk(KERN_WARNING | 131 | printk(KERN_WARNING |
94 | "registering PCI controller with io_map_base unset\n"); | 132 | "registering PCI controller with io_map_base unset\n"); |
95 | } | 133 | } |
134 | |||
135 | /* | ||
136 | * Scan the bus if it is register after the PCI subsystem | ||
137 | * initialization. | ||
138 | */ | ||
139 | if (pci_initialized) { | ||
140 | mutex_lock(&pci_scan_mutex); | ||
141 | pcibios_scanbus(hose); | ||
142 | mutex_unlock(&pci_scan_mutex); | ||
143 | } | ||
144 | |||
96 | return; | 145 | return; |
97 | 146 | ||
98 | out: | 147 | out: |
@@ -125,38 +174,15 @@ static u8 __init common_swizzle(struct pci_dev *dev, u8 *pinp) | |||
125 | static int __init pcibios_init(void) | 174 | static int __init pcibios_init(void) |
126 | { | 175 | { |
127 | struct pci_controller *hose; | 176 | struct pci_controller *hose; |
128 | struct pci_bus *bus; | ||
129 | int next_busno; | ||
130 | int need_domain_info = 0; | ||
131 | 177 | ||
132 | /* Scan all of the recorded PCI controllers. */ | 178 | /* Scan all of the recorded PCI controllers. */ |
133 | for (next_busno = 0, hose = hose_head; hose; hose = hose->next) { | 179 | for (hose = hose_head; hose; hose = hose->next) |
134 | 180 | pcibios_scanbus(hose); | |
135 | if (!hose->iommu) | ||
136 | PCI_DMA_BUS_IS_PHYS = 1; | ||
137 | |||
138 | if (hose->get_busno && pci_probe_only) | ||
139 | next_busno = (*hose->get_busno)(); | ||
140 | |||
141 | bus = pci_scan_bus(next_busno, hose->pci_ops, hose); | ||
142 | hose->bus = bus; | ||
143 | need_domain_info = need_domain_info || hose->index; | ||
144 | hose->need_domain_info = need_domain_info; | ||
145 | if (bus) { | ||
146 | next_busno = bus->subordinate + 1; | ||
147 | /* Don't allow 8-bit bus number overflow inside the hose - | ||
148 | reserve some space for bridges. */ | ||
149 | if (next_busno > 224) { | ||
150 | next_busno = 0; | ||
151 | need_domain_info = 1; | ||
152 | } | ||
153 | } | ||
154 | } | ||
155 | 181 | ||
156 | if (!pci_probe_only) | ||
157 | pci_assign_unassigned_resources(); | ||
158 | pci_fixup_irqs(common_swizzle, pcibios_map_irq); | 182 | pci_fixup_irqs(common_swizzle, pcibios_map_irq); |
159 | 183 | ||
184 | pci_initialized = 1; | ||
185 | |||
160 | return 0; | 186 | return 0; |
161 | } | 187 | } |
162 | 188 | ||