aboutsummaryrefslogtreecommitdiffstats
path: root/arch/tile/kernel
diff options
context:
space:
mode:
authorChris Metcalf <cmetcalf@tilera.com>2011-05-02 15:09:42 -0400
committerChris Metcalf <cmetcalf@tilera.com>2011-05-04 14:39:53 -0400
commit398fa5a9319797e43f67b215337afe62e39475ef (patch)
tree44d966997a6baa6b75a176526d981e3ffb32e471 /arch/tile/kernel
parent313ce674d3cbc2d48ed34a9462427920ac54f4ad (diff)
arch/tile: improve support for PCI hotplug
Note that this is not complete hot-plug support; hot-unplug is not included. Signed-off-by: Chris Metcalf <cmetcalf@tilera.com>
Diffstat (limited to 'arch/tile/kernel')
-rw-r--r--arch/tile/kernel/pci.c207
1 files changed, 117 insertions, 90 deletions
diff --git a/arch/tile/kernel/pci.c b/arch/tile/kernel/pci.c
index ea38f0c9ec7c..65add0270bb6 100644
--- a/arch/tile/kernel/pci.c
+++ b/arch/tile/kernel/pci.c
@@ -1,5 +1,5 @@
1/* 1/*
2 * Copyright 2010 Tilera Corporation. All Rights Reserved. 2 * Copyright 2011 Tilera Corporation. All Rights Reserved.
3 * 3 *
4 * This program is free software; you can redistribute it and/or 4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public License 5 * modify it under the terms of the GNU General Public License
@@ -59,6 +59,7 @@ int __write_once tile_plx_gen1;
59 59
60static struct pci_controller controllers[TILE_NUM_PCIE]; 60static struct pci_controller controllers[TILE_NUM_PCIE];
61static int num_controllers; 61static int num_controllers;
62static int pci_scan_flags[TILE_NUM_PCIE];
62 63
63static struct pci_ops tile_cfg_ops; 64static struct pci_ops tile_cfg_ops;
64 65
@@ -79,7 +80,7 @@ EXPORT_SYMBOL(pcibios_align_resource);
79 * controller_id is the controller number, config type is 0 or 1 for 80 * controller_id is the controller number, config type is 0 or 1 for
80 * config0 or config1 operations. 81 * config0 or config1 operations.
81 */ 82 */
82static int __init tile_pcie_open(int controller_id, int config_type) 83static int __devinit tile_pcie_open(int controller_id, int config_type)
83{ 84{
84 char filename[32]; 85 char filename[32];
85 int fd; 86 int fd;
@@ -95,7 +96,7 @@ static int __init tile_pcie_open(int controller_id, int config_type)
95/* 96/*
96 * Get the IRQ numbers from the HV and set up the handlers for them. 97 * Get the IRQ numbers from the HV and set up the handlers for them.
97 */ 98 */
98static int __init tile_init_irqs(int controller_id, 99static int __devinit tile_init_irqs(int controller_id,
99 struct pci_controller *controller) 100 struct pci_controller *controller)
100{ 101{
101 char filename[32]; 102 char filename[32];
@@ -139,71 +140,80 @@ static int __init tile_init_irqs(int controller_id,
139 * 140 *
140 * Returns the number of controllers discovered. 141 * Returns the number of controllers discovered.
141 */ 142 */
142int __init tile_pci_init(void) 143int __devinit tile_pci_init(void)
143{ 144{
144 int i; 145 int i;
145 146
146 pr_info("PCI: Searching for controllers...\n"); 147 pr_info("PCI: Searching for controllers...\n");
147 148
149 /* Re-init number of PCIe controllers to support hot-plug feature. */
150 num_controllers = 0;
151
148 /* Do any configuration we need before using the PCIe */ 152 /* Do any configuration we need before using the PCIe */
149 153
150 for (i = 0; i < TILE_NUM_PCIE; i++) { 154 for (i = 0; i < TILE_NUM_PCIE; i++) {
151 int hv_cfg_fd0 = -1;
152 int hv_cfg_fd1 = -1;
153 int hv_mem_fd = -1;
154 char name[32];
155 struct pci_controller *controller;
156
157 /* 155 /*
158 * Open the fd to the HV. If it fails then this 156 * To see whether we need a real config op based on
159 * device doesn't exist. 157 * the results of pcibios_init(), to support PCIe hot-plug.
160 */ 158 */
161 hv_cfg_fd0 = tile_pcie_open(i, 0); 159 if (pci_scan_flags[i] == 0) {
162 if (hv_cfg_fd0 < 0) 160 int hv_cfg_fd0 = -1;
163 continue; 161 int hv_cfg_fd1 = -1;
164 hv_cfg_fd1 = tile_pcie_open(i, 1); 162 int hv_mem_fd = -1;
165 if (hv_cfg_fd1 < 0) { 163 char name[32];
166 pr_err("PCI: Couldn't open config fd to HV " 164 struct pci_controller *controller;
167 "for controller %d\n", i); 165
168 goto err_cont; 166 /*
169 } 167 * Open the fd to the HV. If it fails then this
168 * device doesn't exist.
169 */
170 hv_cfg_fd0 = tile_pcie_open(i, 0);
171 if (hv_cfg_fd0 < 0)
172 continue;
173 hv_cfg_fd1 = tile_pcie_open(i, 1);
174 if (hv_cfg_fd1 < 0) {
175 pr_err("PCI: Couldn't open config fd to HV "
176 "for controller %d\n", i);
177 goto err_cont;
178 }
170 179
171 sprintf(name, "pcie/%d/mem", i); 180 sprintf(name, "pcie/%d/mem", i);
172 hv_mem_fd = hv_dev_open((HV_VirtAddr)name, 0); 181 hv_mem_fd = hv_dev_open((HV_VirtAddr)name, 0);
173 if (hv_mem_fd < 0) { 182 if (hv_mem_fd < 0) {
174 pr_err("PCI: Could not open mem fd to HV!\n"); 183 pr_err("PCI: Could not open mem fd to HV!\n");
175 goto err_cont; 184 goto err_cont;
176 } 185 }
177 186
178 pr_info("PCI: Found PCI controller #%d\n", i); 187 pr_info("PCI: Found PCI controller #%d\n", i);
179 188
180 controller = &controllers[num_controllers]; 189 controller = &controllers[i];
181 190
182 if (tile_init_irqs(i, controller)) { 191 if (tile_init_irqs(i, controller)) {
183 pr_err("PCI: Could not initialize " 192 pr_err("PCI: Could not initialize "
184 "IRQs, aborting.\n"); 193 "IRQs, aborting.\n");
185 goto err_cont; 194 goto err_cont;
186 } 195 }
187 196
188 controller->index = num_controllers; 197 controller->index = i;
189 controller->hv_cfg_fd[0] = hv_cfg_fd0; 198 controller->hv_cfg_fd[0] = hv_cfg_fd0;
190 controller->hv_cfg_fd[1] = hv_cfg_fd1; 199 controller->hv_cfg_fd[1] = hv_cfg_fd1;
191 controller->hv_mem_fd = hv_mem_fd; 200 controller->hv_mem_fd = hv_mem_fd;
192 controller->first_busno = 0; 201 controller->first_busno = 0;
193 controller->last_busno = 0xff; 202 controller->last_busno = 0xff;
194 controller->ops = &tile_cfg_ops; 203 controller->ops = &tile_cfg_ops;
195 204
196 num_controllers++; 205 num_controllers++;
197 continue; 206 continue;
198 207
199err_cont: 208err_cont:
200 if (hv_cfg_fd0 >= 0) 209 if (hv_cfg_fd0 >= 0)
201 hv_dev_close(hv_cfg_fd0); 210 hv_dev_close(hv_cfg_fd0);
202 if (hv_cfg_fd1 >= 0) 211 if (hv_cfg_fd1 >= 0)
203 hv_dev_close(hv_cfg_fd1); 212 hv_dev_close(hv_cfg_fd1);
204 if (hv_mem_fd >= 0) 213 if (hv_mem_fd >= 0)
205 hv_dev_close(hv_mem_fd); 214 hv_dev_close(hv_mem_fd);
206 continue; 215 continue;
216 }
207 } 217 }
208 218
209 /* 219 /*
@@ -232,7 +242,7 @@ static int tile_map_irq(struct pci_dev *dev, u8 slot, u8 pin)
232} 242}
233 243
234 244
235static void __init fixup_read_and_payload_sizes(void) 245static void __devinit fixup_read_and_payload_sizes(void)
236{ 246{
237 struct pci_dev *dev = NULL; 247 struct pci_dev *dev = NULL;
238 int smallest_max_payload = 0x1; /* Tile maxes out at 256 bytes. */ 248 int smallest_max_payload = 0x1; /* Tile maxes out at 256 bytes. */
@@ -282,7 +292,7 @@ static void __init fixup_read_and_payload_sizes(void)
282 * The controllers have been set up by the time we get here, by a call to 292 * The controllers have been set up by the time we get here, by a call to
283 * tile_pci_init. 293 * tile_pci_init.
284 */ 294 */
285static int __init pcibios_init(void) 295int __devinit pcibios_init(void)
286{ 296{
287 int i; 297 int i;
288 298
@@ -296,25 +306,31 @@ static int __init pcibios_init(void)
296 mdelay(250); 306 mdelay(250);
297 307
298 /* Scan all of the recorded PCI controllers. */ 308 /* Scan all of the recorded PCI controllers. */
299 for (i = 0; i < num_controllers; i++) { 309 for (i = 0; i < TILE_NUM_PCIE; i++) {
300 struct pci_controller *controller = &controllers[i];
301 struct pci_bus *bus;
302
303 pr_info("PCI: initializing controller #%d\n", i);
304
305 /* 310 /*
306 * This comes from the generic Linux PCI driver. 311 * Do real pcibios init ops if the controller is initialized
307 * 312 * by tile_pci_init() successfully and not initialized by
308 * It reads the PCI tree for this bus into the Linux 313 * pcibios_init() yet to support PCIe hot-plug.
309 * data structures.
310 *
311 * This is inlined in linux/pci.h and calls into
312 * pci_scan_bus_parented() in probe.c.
313 */ 314 */
314 bus = pci_scan_bus(0, controller->ops, controller); 315 if (pci_scan_flags[i] == 0 && controllers[i].ops != NULL) {
315 controller->root_bus = bus; 316 struct pci_controller *controller = &controllers[i];
316 controller->last_busno = bus->subordinate; 317 struct pci_bus *bus;
317 318
319 pr_info("PCI: initializing controller #%d\n", i);
320
321 /*
322 * This comes from the generic Linux PCI driver.
323 *
324 * It reads the PCI tree for this bus into the Linux
325 * data structures.
326 *
327 * This is inlined in linux/pci.h and calls into
328 * pci_scan_bus_parented() in probe.c.
329 */
330 bus = pci_scan_bus(0, controller->ops, controller);
331 controller->root_bus = bus;
332 controller->last_busno = bus->subordinate;
333 }
318 } 334 }
319 335
320 /* Do machine dependent PCI interrupt routing */ 336 /* Do machine dependent PCI interrupt routing */
@@ -326,34 +342,45 @@ static int __init pcibios_init(void)
326 * It allocates all of the resources (I/O memory, etc) 342 * It allocates all of the resources (I/O memory, etc)
327 * associated with the devices read in above. 343 * associated with the devices read in above.
328 */ 344 */
329
330 pci_assign_unassigned_resources(); 345 pci_assign_unassigned_resources();
331 346
332 /* Configure the max_read_size and max_payload_size values. */ 347 /* Configure the max_read_size and max_payload_size values. */
333 fixup_read_and_payload_sizes(); 348 fixup_read_and_payload_sizes();
334 349
335 /* Record the I/O resources in the PCI controller structure. */ 350 /* Record the I/O resources in the PCI controller structure. */
336 for (i = 0; i < num_controllers; i++) { 351 for (i = 0; i < TILE_NUM_PCIE; i++) {
337 struct pci_bus *root_bus = controllers[i].root_bus; 352 /*
338 struct pci_bus *next_bus; 353 * Do real pcibios init ops if the controller is initialized
339 struct pci_dev *dev; 354 * by tile_pci_init() successfully and not initialized by
340 355 * pcibios_init() yet to support PCIe hot-plug.
341 list_for_each_entry(dev, &root_bus->devices, bus_list) { 356 */
342 /* Find the PCI host controller, ie. the 1st bridge. */ 357 if (pci_scan_flags[i] == 0 && controllers[i].ops != NULL) {
343 if ((dev->class >> 8) == PCI_CLASS_BRIDGE_PCI && 358 struct pci_bus *root_bus = controllers[i].root_bus;
344 (PCI_SLOT(dev->devfn) == 0)) { 359 struct pci_bus *next_bus;
345 next_bus = dev->subordinate; 360 struct pci_dev *dev;
346 controllers[i].mem_resources[0] = 361
347 *next_bus->resource[0]; 362 list_for_each_entry(dev, &root_bus->devices, bus_list) {
348 controllers[i].mem_resources[1] = 363 /*
349 *next_bus->resource[1]; 364 * Find the PCI host controller, ie. the 1st
350 controllers[i].mem_resources[2] = 365 * bridge.
351 *next_bus->resource[2]; 366 */
352 367 if ((dev->class >> 8) == PCI_CLASS_BRIDGE_PCI &&
353 break; 368 (PCI_SLOT(dev->devfn) == 0)) {
369 next_bus = dev->subordinate;
370 controllers[i].mem_resources[0] =
371 *next_bus->resource[0];
372 controllers[i].mem_resources[1] =
373 *next_bus->resource[1];
374 controllers[i].mem_resources[2] =
375 *next_bus->resource[2];
376
377 /* Setup flags. */
378 pci_scan_flags[i] = 1;
379
380 break;
381 }
354 } 382 }
355 } 383 }
356
357 } 384 }
358 385
359 return 0; 386 return 0;
@@ -381,7 +408,7 @@ char __devinit *pcibios_setup(char *str)
381/* 408/*
382 * This is called from the generic Linux layer. 409 * This is called from the generic Linux layer.
383 */ 410 */
384void __init pcibios_update_irq(struct pci_dev *dev, int irq) 411void __devinit pcibios_update_irq(struct pci_dev *dev, int irq)
385{ 412{
386 pci_write_config_byte(dev, PCI_INTERRUPT_LINE, irq); 413 pci_write_config_byte(dev, PCI_INTERRUPT_LINE, irq);
387} 414}