diff options
| -rw-r--r-- | arch/tile/Kconfig | 8 | ||||
| -rw-r--r-- | arch/tile/include/asm/pci.h | 3 | ||||
| -rw-r--r-- | arch/tile/kernel/pci.c | 207 |
3 files changed, 127 insertions, 91 deletions
diff --git a/arch/tile/Kconfig b/arch/tile/Kconfig index e32b0c23c4c8..635e1bfb1c5d 100644 --- a/arch/tile/Kconfig +++ b/arch/tile/Kconfig | |||
| @@ -339,6 +339,14 @@ config NO_IOPORT | |||
| 339 | 339 | ||
| 340 | source "drivers/pci/Kconfig" | 340 | source "drivers/pci/Kconfig" |
| 341 | 341 | ||
| 342 | config HOTPLUG | ||
| 343 | bool "Support for hot-pluggable devices" | ||
| 344 | ---help--- | ||
| 345 | Say Y here if you want to plug devices into your computer while | ||
| 346 | the system is running, and be able to use them quickly. In many | ||
| 347 | cases, the devices can likewise be unplugged at any time too. | ||
| 348 | One well-known example of this is USB. | ||
| 349 | |||
| 342 | source "drivers/pci/hotplug/Kconfig" | 350 | source "drivers/pci/hotplug/Kconfig" |
| 343 | 351 | ||
| 344 | endmenu | 352 | endmenu |
diff --git a/arch/tile/include/asm/pci.h b/arch/tile/include/asm/pci.h index c3fc458a0d32..7f03cefed1b9 100644 --- a/arch/tile/include/asm/pci.h +++ b/arch/tile/include/asm/pci.h | |||
| @@ -46,7 +46,8 @@ struct pci_controller { | |||
| 46 | */ | 46 | */ |
| 47 | #define PCI_DMA_BUS_IS_PHYS 1 | 47 | #define PCI_DMA_BUS_IS_PHYS 1 |
| 48 | 48 | ||
| 49 | int __init tile_pci_init(void); | 49 | int __devinit tile_pci_init(void); |
| 50 | int __devinit pcibios_init(void); | ||
| 50 | 51 | ||
| 51 | void __iomem *pci_iomap(struct pci_dev *dev, int bar, unsigned long max); | 52 | void __iomem *pci_iomap(struct pci_dev *dev, int bar, unsigned long max); |
| 52 | static inline void pci_iounmap(struct pci_dev *dev, void __iomem *addr) {} | 53 | static inline void pci_iounmap(struct pci_dev *dev, void __iomem *addr) {} |
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 | ||
| 60 | static struct pci_controller controllers[TILE_NUM_PCIE]; | 60 | static struct pci_controller controllers[TILE_NUM_PCIE]; |
| 61 | static int num_controllers; | 61 | static int num_controllers; |
| 62 | static int pci_scan_flags[TILE_NUM_PCIE]; | ||
| 62 | 63 | ||
| 63 | static struct pci_ops tile_cfg_ops; | 64 | static 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 | */ |
| 82 | static int __init tile_pcie_open(int controller_id, int config_type) | 83 | static 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 | */ |
| 98 | static int __init tile_init_irqs(int controller_id, | 99 | static 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 | */ |
| 142 | int __init tile_pci_init(void) | 143 | int __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 | ||
| 199 | err_cont: | 208 | err_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 | ||
| 235 | static void __init fixup_read_and_payload_sizes(void) | 245 | static 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 | */ |
| 285 | static int __init pcibios_init(void) | 295 | int __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 | */ |
| 384 | void __init pcibios_update_irq(struct pci_dev *dev, int irq) | 411 | void __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 | } |
