diff options
Diffstat (limited to 'arch/powerpc/platforms/pseries')
-rw-r--r-- | arch/powerpc/platforms/pseries/iommu.c | 90 | ||||
-rw-r--r-- | arch/powerpc/platforms/pseries/lpar.c | 4 | ||||
-rw-r--r-- | arch/powerpc/platforms/pseries/pci.c | 35 | ||||
-rw-r--r-- | arch/powerpc/platforms/pseries/pci_dlpar.c | 6 | ||||
-rw-r--r-- | arch/powerpc/platforms/pseries/reconfig.c | 3 | ||||
-rw-r--r-- | arch/powerpc/platforms/pseries/setup.c | 5 | ||||
-rw-r--r-- | arch/powerpc/platforms/pseries/xics.c | 68 |
7 files changed, 105 insertions, 106 deletions
diff --git a/arch/powerpc/platforms/pseries/iommu.c b/arch/powerpc/platforms/pseries/iommu.c index 556c279a789d..3c95392f4f41 100644 --- a/arch/powerpc/platforms/pseries/iommu.c +++ b/arch/powerpc/platforms/pseries/iommu.c | |||
@@ -309,7 +309,7 @@ static void iommu_table_setparms_lpar(struct pci_controller *phb, | |||
309 | tbl->it_size = size >> IOMMU_PAGE_SHIFT; | 309 | tbl->it_size = size >> IOMMU_PAGE_SHIFT; |
310 | } | 310 | } |
311 | 311 | ||
312 | static void iommu_bus_setup_pSeries(struct pci_bus *bus) | 312 | static void pci_dma_bus_setup_pSeries(struct pci_bus *bus) |
313 | { | 313 | { |
314 | struct device_node *dn; | 314 | struct device_node *dn; |
315 | struct iommu_table *tbl; | 315 | struct iommu_table *tbl; |
@@ -318,10 +318,9 @@ static void iommu_bus_setup_pSeries(struct pci_bus *bus) | |||
318 | struct pci_dn *pci; | 318 | struct pci_dn *pci; |
319 | int children; | 319 | int children; |
320 | 320 | ||
321 | DBG("iommu_bus_setup_pSeries, bus %p, bus->self %p\n", bus, bus->self); | ||
322 | |||
323 | dn = pci_bus_to_OF_node(bus); | 321 | dn = pci_bus_to_OF_node(bus); |
324 | pci = PCI_DN(dn); | 322 | |
323 | DBG("pci_dma_bus_setup_pSeries: setting up bus %s\n", dn->full_name); | ||
325 | 324 | ||
326 | if (bus->self) { | 325 | if (bus->self) { |
327 | /* This is not a root bus, any setup will be done for the | 326 | /* This is not a root bus, any setup will be done for the |
@@ -329,6 +328,7 @@ static void iommu_bus_setup_pSeries(struct pci_bus *bus) | |||
329 | */ | 328 | */ |
330 | return; | 329 | return; |
331 | } | 330 | } |
331 | pci = PCI_DN(dn); | ||
332 | 332 | ||
333 | /* Check if the ISA bus on the system is under | 333 | /* Check if the ISA bus on the system is under |
334 | * this PHB. | 334 | * this PHB. |
@@ -390,17 +390,17 @@ static void iommu_bus_setup_pSeries(struct pci_bus *bus) | |||
390 | } | 390 | } |
391 | 391 | ||
392 | 392 | ||
393 | static void iommu_bus_setup_pSeriesLP(struct pci_bus *bus) | 393 | static void pci_dma_bus_setup_pSeriesLP(struct pci_bus *bus) |
394 | { | 394 | { |
395 | struct iommu_table *tbl; | 395 | struct iommu_table *tbl; |
396 | struct device_node *dn, *pdn; | 396 | struct device_node *dn, *pdn; |
397 | struct pci_dn *ppci; | 397 | struct pci_dn *ppci; |
398 | const void *dma_window = NULL; | 398 | const void *dma_window = NULL; |
399 | 399 | ||
400 | DBG("iommu_bus_setup_pSeriesLP, bus %p, bus->self %p\n", bus, bus->self); | ||
401 | |||
402 | dn = pci_bus_to_OF_node(bus); | 400 | dn = pci_bus_to_OF_node(bus); |
403 | 401 | ||
402 | DBG("pci_dma_bus_setup_pSeriesLP: setting up bus %s\n", dn->full_name); | ||
403 | |||
404 | /* Find nearest ibm,dma-window, walking up the device tree */ | 404 | /* Find nearest ibm,dma-window, walking up the device tree */ |
405 | for (pdn = dn; pdn != NULL; pdn = pdn->parent) { | 405 | for (pdn = dn; pdn != NULL; pdn = pdn->parent) { |
406 | dma_window = get_property(pdn, "ibm,dma-window", NULL); | 406 | dma_window = get_property(pdn, "ibm,dma-window", NULL); |
@@ -409,11 +409,15 @@ static void iommu_bus_setup_pSeriesLP(struct pci_bus *bus) | |||
409 | } | 409 | } |
410 | 410 | ||
411 | if (dma_window == NULL) { | 411 | if (dma_window == NULL) { |
412 | DBG("iommu_bus_setup_pSeriesLP: bus %s seems to have no ibm,dma-window property\n", dn->full_name); | 412 | DBG(" no ibm,dma-window property !\n"); |
413 | return; | 413 | return; |
414 | } | 414 | } |
415 | 415 | ||
416 | ppci = PCI_DN(pdn); | 416 | ppci = PCI_DN(pdn); |
417 | |||
418 | DBG(" parent is %s, iommu_table: 0x%p\n", | ||
419 | pdn->full_name, ppci->iommu_table); | ||
420 | |||
417 | if (!ppci->iommu_table) { | 421 | if (!ppci->iommu_table) { |
418 | /* Bussubno hasn't been copied yet. | 422 | /* Bussubno hasn't been copied yet. |
419 | * Do it now because iommu_table_setparms_lpar needs it. | 423 | * Do it now because iommu_table_setparms_lpar needs it. |
@@ -427,6 +431,7 @@ static void iommu_bus_setup_pSeriesLP(struct pci_bus *bus) | |||
427 | iommu_table_setparms_lpar(ppci->phb, pdn, tbl, dma_window); | 431 | iommu_table_setparms_lpar(ppci->phb, pdn, tbl, dma_window); |
428 | 432 | ||
429 | ppci->iommu_table = iommu_init_table(tbl, ppci->phb->node); | 433 | ppci->iommu_table = iommu_init_table(tbl, ppci->phb->node); |
434 | DBG(" created table: %p\n", ppci->iommu_table); | ||
430 | } | 435 | } |
431 | 436 | ||
432 | if (pdn != dn) | 437 | if (pdn != dn) |
@@ -434,27 +439,27 @@ static void iommu_bus_setup_pSeriesLP(struct pci_bus *bus) | |||
434 | } | 439 | } |
435 | 440 | ||
436 | 441 | ||
437 | static void iommu_dev_setup_pSeries(struct pci_dev *dev) | 442 | static void pci_dma_dev_setup_pSeries(struct pci_dev *dev) |
438 | { | 443 | { |
439 | struct device_node *dn, *mydn; | 444 | struct device_node *dn; |
440 | struct iommu_table *tbl; | 445 | struct iommu_table *tbl; |
441 | 446 | ||
442 | DBG("iommu_dev_setup_pSeries, dev %p (%s)\n", dev, pci_name(dev)); | 447 | DBG("pci_dma_dev_setup_pSeries: %s\n", pci_name(dev)); |
443 | 448 | ||
444 | mydn = dn = pci_device_to_OF_node(dev); | 449 | dn = dev->dev.archdata.of_node; |
445 | 450 | ||
446 | /* If we're the direct child of a root bus, then we need to allocate | 451 | /* If we're the direct child of a root bus, then we need to allocate |
447 | * an iommu table ourselves. The bus setup code should have setup | 452 | * an iommu table ourselves. The bus setup code should have setup |
448 | * the window sizes already. | 453 | * the window sizes already. |
449 | */ | 454 | */ |
450 | if (!dev->bus->self) { | 455 | if (!dev->bus->self) { |
456 | struct pci_controller *phb = PCI_DN(dn)->phb; | ||
457 | |||
451 | DBG(" --> first child, no bridge. Allocating iommu table.\n"); | 458 | DBG(" --> first child, no bridge. Allocating iommu table.\n"); |
452 | tbl = kmalloc_node(sizeof(struct iommu_table), GFP_KERNEL, | 459 | tbl = kmalloc_node(sizeof(struct iommu_table), GFP_KERNEL, |
453 | PCI_DN(dn)->phb->node); | 460 | phb->node); |
454 | iommu_table_setparms(PCI_DN(dn)->phb, dn, tbl); | 461 | iommu_table_setparms(phb, dn, tbl); |
455 | PCI_DN(dn)->iommu_table = iommu_init_table(tbl, | 462 | dev->dev.archdata.dma_data = iommu_init_table(tbl, phb->node); |
456 | PCI_DN(dn)->phb->node); | ||
457 | |||
458 | return; | 463 | return; |
459 | } | 464 | } |
460 | 465 | ||
@@ -465,11 +470,11 @@ static void iommu_dev_setup_pSeries(struct pci_dev *dev) | |||
465 | while (dn && PCI_DN(dn) && PCI_DN(dn)->iommu_table == NULL) | 470 | while (dn && PCI_DN(dn) && PCI_DN(dn)->iommu_table == NULL) |
466 | dn = dn->parent; | 471 | dn = dn->parent; |
467 | 472 | ||
468 | if (dn && PCI_DN(dn)) { | 473 | if (dn && PCI_DN(dn)) |
469 | PCI_DN(mydn)->iommu_table = PCI_DN(dn)->iommu_table; | 474 | dev->dev.archdata.dma_data = PCI_DN(dn)->iommu_table; |
470 | } else { | 475 | else |
471 | DBG("iommu_dev_setup_pSeries, dev %p (%s) has no iommu table\n", dev, pci_name(dev)); | 476 | printk(KERN_WARNING "iommu: Device %s has no iommu table\n", |
472 | } | 477 | pci_name(dev)); |
473 | } | 478 | } |
474 | 479 | ||
475 | static int iommu_reconfig_notifier(struct notifier_block *nb, unsigned long action, void *node) | 480 | static int iommu_reconfig_notifier(struct notifier_block *nb, unsigned long action, void *node) |
@@ -495,13 +500,15 @@ static struct notifier_block iommu_reconfig_nb = { | |||
495 | .notifier_call = iommu_reconfig_notifier, | 500 | .notifier_call = iommu_reconfig_notifier, |
496 | }; | 501 | }; |
497 | 502 | ||
498 | static void iommu_dev_setup_pSeriesLP(struct pci_dev *dev) | 503 | static void pci_dma_dev_setup_pSeriesLP(struct pci_dev *dev) |
499 | { | 504 | { |
500 | struct device_node *pdn, *dn; | 505 | struct device_node *pdn, *dn; |
501 | struct iommu_table *tbl; | 506 | struct iommu_table *tbl; |
502 | const void *dma_window = NULL; | 507 | const void *dma_window = NULL; |
503 | struct pci_dn *pci; | 508 | struct pci_dn *pci; |
504 | 509 | ||
510 | DBG("pci_dma_dev_setup_pSeriesLP: %s\n", pci_name(dev)); | ||
511 | |||
505 | /* dev setup for LPAR is a little tricky, since the device tree might | 512 | /* dev setup for LPAR is a little tricky, since the device tree might |
506 | * contain the dma-window properties per-device and not neccesarily | 513 | * contain the dma-window properties per-device and not neccesarily |
507 | * for the bus. So we need to search upwards in the tree until we | 514 | * for the bus. So we need to search upwards in the tree until we |
@@ -509,9 +516,7 @@ static void iommu_dev_setup_pSeriesLP(struct pci_dev *dev) | |||
509 | * already allocated. | 516 | * already allocated. |
510 | */ | 517 | */ |
511 | dn = pci_device_to_OF_node(dev); | 518 | dn = pci_device_to_OF_node(dev); |
512 | 519 | DBG(" node is %s\n", dn->full_name); | |
513 | DBG("iommu_dev_setup_pSeriesLP, dev %p (%s) %s\n", | ||
514 | dev, pci_name(dev), dn->full_name); | ||
515 | 520 | ||
516 | for (pdn = dn; pdn && PCI_DN(pdn) && !PCI_DN(pdn)->iommu_table; | 521 | for (pdn = dn; pdn && PCI_DN(pdn) && !PCI_DN(pdn)->iommu_table; |
517 | pdn = pdn->parent) { | 522 | pdn = pdn->parent) { |
@@ -520,16 +525,17 @@ static void iommu_dev_setup_pSeriesLP(struct pci_dev *dev) | |||
520 | break; | 525 | break; |
521 | } | 526 | } |
522 | 527 | ||
528 | DBG(" parent is %s\n", pdn->full_name); | ||
529 | |||
523 | /* Check for parent == NULL so we don't try to setup the empty EADS | 530 | /* Check for parent == NULL so we don't try to setup the empty EADS |
524 | * slots on POWER4 machines. | 531 | * slots on POWER4 machines. |
525 | */ | 532 | */ |
526 | if (dma_window == NULL || pdn->parent == NULL) { | 533 | if (dma_window == NULL || pdn->parent == NULL) { |
527 | DBG("No dma window for device, linking to parent\n"); | 534 | DBG(" no dma window for device, linking to parent\n"); |
528 | PCI_DN(dn)->iommu_table = PCI_DN(pdn)->iommu_table; | 535 | dev->dev.archdata.dma_data = PCI_DN(pdn)->iommu_table; |
529 | return; | 536 | return; |
530 | } else { | ||
531 | DBG("Found DMA window, allocating table\n"); | ||
532 | } | 537 | } |
538 | DBG(" found DMA window, table: %p\n", pci->iommu_table); | ||
533 | 539 | ||
534 | pci = PCI_DN(pdn); | 540 | pci = PCI_DN(pdn); |
535 | if (!pci->iommu_table) { | 541 | if (!pci->iommu_table) { |
@@ -542,24 +548,20 @@ static void iommu_dev_setup_pSeriesLP(struct pci_dev *dev) | |||
542 | iommu_table_setparms_lpar(pci->phb, pdn, tbl, dma_window); | 548 | iommu_table_setparms_lpar(pci->phb, pdn, tbl, dma_window); |
543 | 549 | ||
544 | pci->iommu_table = iommu_init_table(tbl, pci->phb->node); | 550 | pci->iommu_table = iommu_init_table(tbl, pci->phb->node); |
551 | DBG(" created table: %p\n", pci->iommu_table); | ||
545 | } | 552 | } |
546 | 553 | ||
547 | if (pdn != dn) | 554 | dev->dev.archdata.dma_data = pci->iommu_table; |
548 | PCI_DN(dn)->iommu_table = pci->iommu_table; | ||
549 | } | 555 | } |
550 | 556 | ||
551 | static void iommu_bus_setup_null(struct pci_bus *b) { } | ||
552 | static void iommu_dev_setup_null(struct pci_dev *d) { } | ||
553 | |||
554 | /* These are called very early. */ | 557 | /* These are called very early. */ |
555 | void iommu_init_early_pSeries(void) | 558 | void iommu_init_early_pSeries(void) |
556 | { | 559 | { |
557 | if (of_chosen && get_property(of_chosen, "linux,iommu-off", NULL)) { | 560 | if (of_chosen && get_property(of_chosen, "linux,iommu-off", NULL)) { |
558 | /* Direct I/O, IOMMU off */ | 561 | /* Direct I/O, IOMMU off */ |
559 | ppc_md.iommu_dev_setup = iommu_dev_setup_null; | 562 | ppc_md.pci_dma_dev_setup = NULL; |
560 | ppc_md.iommu_bus_setup = iommu_bus_setup_null; | 563 | ppc_md.pci_dma_bus_setup = NULL; |
561 | pci_direct_iommu_init(); | 564 | pci_dma_ops = &dma_direct_ops; |
562 | |||
563 | return; | 565 | return; |
564 | } | 566 | } |
565 | 567 | ||
@@ -572,19 +574,19 @@ void iommu_init_early_pSeries(void) | |||
572 | ppc_md.tce_free = tce_free_pSeriesLP; | 574 | ppc_md.tce_free = tce_free_pSeriesLP; |
573 | } | 575 | } |
574 | ppc_md.tce_get = tce_get_pSeriesLP; | 576 | ppc_md.tce_get = tce_get_pSeriesLP; |
575 | ppc_md.iommu_bus_setup = iommu_bus_setup_pSeriesLP; | 577 | ppc_md.pci_dma_bus_setup = pci_dma_bus_setup_pSeriesLP; |
576 | ppc_md.iommu_dev_setup = iommu_dev_setup_pSeriesLP; | 578 | ppc_md.pci_dma_dev_setup = pci_dma_dev_setup_pSeriesLP; |
577 | } else { | 579 | } else { |
578 | ppc_md.tce_build = tce_build_pSeries; | 580 | ppc_md.tce_build = tce_build_pSeries; |
579 | ppc_md.tce_free = tce_free_pSeries; | 581 | ppc_md.tce_free = tce_free_pSeries; |
580 | ppc_md.tce_get = tce_get_pseries; | 582 | ppc_md.tce_get = tce_get_pseries; |
581 | ppc_md.iommu_bus_setup = iommu_bus_setup_pSeries; | 583 | ppc_md.pci_dma_bus_setup = pci_dma_bus_setup_pSeries; |
582 | ppc_md.iommu_dev_setup = iommu_dev_setup_pSeries; | 584 | ppc_md.pci_dma_dev_setup = pci_dma_dev_setup_pSeries; |
583 | } | 585 | } |
584 | 586 | ||
585 | 587 | ||
586 | pSeries_reconfig_notifier_register(&iommu_reconfig_nb); | 588 | pSeries_reconfig_notifier_register(&iommu_reconfig_nb); |
587 | 589 | ||
588 | pci_iommu_init(); | 590 | pci_dma_ops = &dma_iommu_ops; |
589 | } | 591 | } |
590 | 592 | ||
diff --git a/arch/powerpc/platforms/pseries/lpar.c b/arch/powerpc/platforms/pseries/lpar.c index 1820a0b0a8c6..721436db3ef0 100644 --- a/arch/powerpc/platforms/pseries/lpar.c +++ b/arch/powerpc/platforms/pseries/lpar.c | |||
@@ -282,7 +282,7 @@ void vpa_init(int cpu) | |||
282 | } | 282 | } |
283 | } | 283 | } |
284 | 284 | ||
285 | long pSeries_lpar_hpte_insert(unsigned long hpte_group, | 285 | static long pSeries_lpar_hpte_insert(unsigned long hpte_group, |
286 | unsigned long va, unsigned long pa, | 286 | unsigned long va, unsigned long pa, |
287 | unsigned long rflags, unsigned long vflags, | 287 | unsigned long rflags, unsigned long vflags, |
288 | int psize) | 288 | int psize) |
@@ -506,7 +506,7 @@ static void pSeries_lpar_hpte_invalidate(unsigned long slot, unsigned long va, | |||
506 | * Take a spinlock around flushes to avoid bouncing the hypervisor tlbie | 506 | * Take a spinlock around flushes to avoid bouncing the hypervisor tlbie |
507 | * lock. | 507 | * lock. |
508 | */ | 508 | */ |
509 | void pSeries_lpar_flush_hash_range(unsigned long number, int local) | 509 | static void pSeries_lpar_flush_hash_range(unsigned long number, int local) |
510 | { | 510 | { |
511 | int i; | 511 | int i; |
512 | unsigned long flags = 0; | 512 | unsigned long flags = 0; |
diff --git a/arch/powerpc/platforms/pseries/pci.c b/arch/powerpc/platforms/pseries/pci.c index 410a6bcc4ca0..715db5c89908 100644 --- a/arch/powerpc/platforms/pseries/pci.c +++ b/arch/powerpc/platforms/pseries/pci.c | |||
@@ -29,8 +29,6 @@ | |||
29 | #include <asm/prom.h> | 29 | #include <asm/prom.h> |
30 | #include <asm/ppc-pci.h> | 30 | #include <asm/ppc-pci.h> |
31 | 31 | ||
32 | static int __devinitdata s7a_workaround = -1; | ||
33 | |||
34 | #if 0 | 32 | #if 0 |
35 | void pcibios_name_device(struct pci_dev *dev) | 33 | void pcibios_name_device(struct pci_dev *dev) |
36 | { | 34 | { |
@@ -57,39 +55,6 @@ void pcibios_name_device(struct pci_dev *dev) | |||
57 | DECLARE_PCI_FIXUP_HEADER(PCI_ANY_ID, PCI_ANY_ID, pcibios_name_device); | 55 | DECLARE_PCI_FIXUP_HEADER(PCI_ANY_ID, PCI_ANY_ID, pcibios_name_device); |
58 | #endif | 56 | #endif |
59 | 57 | ||
60 | static void __devinit check_s7a(void) | ||
61 | { | ||
62 | struct device_node *root; | ||
63 | const char *model; | ||
64 | |||
65 | s7a_workaround = 0; | ||
66 | root = of_find_node_by_path("/"); | ||
67 | if (root) { | ||
68 | model = get_property(root, "model", NULL); | ||
69 | if (model && !strcmp(model, "IBM,7013-S7A")) | ||
70 | s7a_workaround = 1; | ||
71 | of_node_put(root); | ||
72 | } | ||
73 | } | ||
74 | |||
75 | void __devinit pSeries_irq_bus_setup(struct pci_bus *bus) | ||
76 | { | ||
77 | struct pci_dev *dev; | ||
78 | |||
79 | if (s7a_workaround < 0) | ||
80 | check_s7a(); | ||
81 | list_for_each_entry(dev, &bus->devices, bus_list) { | ||
82 | pci_read_irq_line(dev); | ||
83 | if (s7a_workaround) { | ||
84 | if (dev->irq > 16) { | ||
85 | dev->irq -= 3; | ||
86 | pci_write_config_byte(dev, PCI_INTERRUPT_LINE, | ||
87 | dev->irq); | ||
88 | } | ||
89 | } | ||
90 | } | ||
91 | } | ||
92 | |||
93 | static void __init pSeries_request_regions(void) | 58 | static void __init pSeries_request_regions(void) |
94 | { | 59 | { |
95 | if (!isa_io_base) | 60 | if (!isa_io_base) |
diff --git a/arch/powerpc/platforms/pseries/pci_dlpar.c b/arch/powerpc/platforms/pseries/pci_dlpar.c index 6bfacc217085..ac56b868913a 100644 --- a/arch/powerpc/platforms/pseries/pci_dlpar.c +++ b/arch/powerpc/platforms/pseries/pci_dlpar.c | |||
@@ -93,8 +93,8 @@ pcibios_fixup_new_pci_devices(struct pci_bus *bus, int fix_bus) | |||
93 | if (list_empty(&dev->global_list)) { | 93 | if (list_empty(&dev->global_list)) { |
94 | int i; | 94 | int i; |
95 | 95 | ||
96 | /* Need to setup IOMMU tables */ | 96 | /* Fill device archdata and setup iommu table */ |
97 | ppc_md.iommu_dev_setup(dev); | 97 | pcibios_setup_new_device(dev); |
98 | 98 | ||
99 | if(fix_bus) | 99 | if(fix_bus) |
100 | pcibios_fixup_device_resources(dev, bus); | 100 | pcibios_fixup_device_resources(dev, bus); |
@@ -195,7 +195,7 @@ struct pci_controller * __devinit init_phb_dynamic(struct device_node *dn) | |||
195 | phb = pcibios_alloc_controller(dn); | 195 | phb = pcibios_alloc_controller(dn); |
196 | if (!phb) | 196 | if (!phb) |
197 | return NULL; | 197 | return NULL; |
198 | setup_phb(dn, phb); | 198 | rtas_setup_phb(phb); |
199 | pci_process_bridge_OF_ranges(phb, dn, 0); | 199 | pci_process_bridge_OF_ranges(phb, dn, 0); |
200 | 200 | ||
201 | pci_setup_phb_io_dynamic(phb, primary); | 201 | pci_setup_phb_io_dynamic(phb, primary); |
diff --git a/arch/powerpc/platforms/pseries/reconfig.c b/arch/powerpc/platforms/pseries/reconfig.c index 1773103354be..4ad33e41b008 100644 --- a/arch/powerpc/platforms/pseries/reconfig.c +++ b/arch/powerpc/platforms/pseries/reconfig.c | |||
@@ -268,11 +268,10 @@ static char * parse_next_property(char *buf, char *end, char **name, int *length | |||
268 | static struct property *new_property(const char *name, const int length, | 268 | static struct property *new_property(const char *name, const int length, |
269 | const unsigned char *value, struct property *last) | 269 | const unsigned char *value, struct property *last) |
270 | { | 270 | { |
271 | struct property *new = kmalloc(sizeof(*new), GFP_KERNEL); | 271 | struct property *new = kzalloc(sizeof(*new), GFP_KERNEL); |
272 | 272 | ||
273 | if (!new) | 273 | if (!new) |
274 | return NULL; | 274 | return NULL; |
275 | memset(new, 0, sizeof(*new)); | ||
276 | 275 | ||
277 | if (!(new->name = kmalloc(strlen(name) + 1, GFP_KERNEL))) | 276 | if (!(new->name = kmalloc(strlen(name) + 1, GFP_KERNEL))) |
278 | goto cleanup; | 277 | goto cleanup; |
diff --git a/arch/powerpc/platforms/pseries/setup.c b/arch/powerpc/platforms/pseries/setup.c index 89a8119f988d..0dc2548ca9bc 100644 --- a/arch/powerpc/platforms/pseries/setup.c +++ b/arch/powerpc/platforms/pseries/setup.c | |||
@@ -347,6 +347,7 @@ static int __init pSeries_init_panel(void) | |||
347 | } | 347 | } |
348 | arch_initcall(pSeries_init_panel); | 348 | arch_initcall(pSeries_init_panel); |
349 | 349 | ||
350 | #ifdef CONFIG_HOTPLUG_CPU | ||
350 | static void pSeries_mach_cpu_die(void) | 351 | static void pSeries_mach_cpu_die(void) |
351 | { | 352 | { |
352 | local_irq_disable(); | 353 | local_irq_disable(); |
@@ -357,6 +358,9 @@ static void pSeries_mach_cpu_die(void) | |||
357 | BUG(); | 358 | BUG(); |
358 | for(;;); | 359 | for(;;); |
359 | } | 360 | } |
361 | #else | ||
362 | #define pSeries_mach_cpu_die NULL | ||
363 | #endif | ||
360 | 364 | ||
361 | static int pseries_set_dabr(unsigned long dabr) | 365 | static int pseries_set_dabr(unsigned long dabr) |
362 | { | 366 | { |
@@ -553,7 +557,6 @@ define_machine(pseries) { | |||
553 | .log_error = pSeries_log_error, | 557 | .log_error = pSeries_log_error, |
554 | .pcibios_fixup = pSeries_final_fixup, | 558 | .pcibios_fixup = pSeries_final_fixup, |
555 | .pci_probe_mode = pSeries_pci_probe_mode, | 559 | .pci_probe_mode = pSeries_pci_probe_mode, |
556 | .irq_bus_setup = pSeries_irq_bus_setup, | ||
557 | .restart = rtas_restart, | 560 | .restart = rtas_restart, |
558 | .power_off = rtas_power_off, | 561 | .power_off = rtas_power_off, |
559 | .halt = rtas_halt, | 562 | .halt = rtas_halt, |
diff --git a/arch/powerpc/platforms/pseries/xics.c b/arch/powerpc/platforms/pseries/xics.c index d071abe78ab1..b5b2b1103de8 100644 --- a/arch/powerpc/platforms/pseries/xics.c +++ b/arch/powerpc/platforms/pseries/xics.c | |||
@@ -656,13 +656,38 @@ static void __init xics_setup_8259_cascade(void) | |||
656 | set_irq_chained_handler(cascade, pseries_8259_cascade); | 656 | set_irq_chained_handler(cascade, pseries_8259_cascade); |
657 | } | 657 | } |
658 | 658 | ||
659 | static struct device_node *cpuid_to_of_node(int cpu) | ||
660 | { | ||
661 | struct device_node *np; | ||
662 | u32 hcpuid = get_hard_smp_processor_id(cpu); | ||
663 | |||
664 | for_each_node_by_type(np, "cpu") { | ||
665 | int i, len; | ||
666 | const u32 *intserv; | ||
667 | |||
668 | intserv = get_property(np, "ibm,ppc-interrupt-server#s", &len); | ||
669 | |||
670 | if (!intserv) | ||
671 | intserv = get_property(np, "reg", &len); | ||
672 | |||
673 | i = len / sizeof(u32); | ||
674 | |||
675 | while (i--) | ||
676 | if (intserv[i] == hcpuid) | ||
677 | return np; | ||
678 | } | ||
679 | |||
680 | return NULL; | ||
681 | } | ||
682 | |||
659 | void __init xics_init_IRQ(void) | 683 | void __init xics_init_IRQ(void) |
660 | { | 684 | { |
661 | int i; | 685 | int i, j; |
662 | struct device_node *np; | 686 | struct device_node *np; |
663 | u32 ilen, indx = 0; | 687 | u32 ilen, indx = 0; |
664 | const u32 *ireg; | 688 | const u32 *ireg, *isize; |
665 | int found = 0; | 689 | int found = 0; |
690 | u32 hcpuid; | ||
666 | 691 | ||
667 | ppc64_boot_msg(0x20, "XICS Init"); | 692 | ppc64_boot_msg(0x20, "XICS Init"); |
668 | 693 | ||
@@ -683,26 +708,31 @@ void __init xics_init_IRQ(void) | |||
683 | xics_init_host(); | 708 | xics_init_host(); |
684 | 709 | ||
685 | /* Find the server numbers for the boot cpu. */ | 710 | /* Find the server numbers for the boot cpu. */ |
686 | for (np = of_find_node_by_type(NULL, "cpu"); | 711 | np = cpuid_to_of_node(boot_cpuid); |
687 | np; | 712 | BUG_ON(!np); |
688 | np = of_find_node_by_type(np, "cpu")) { | 713 | ireg = get_property(np, "ibm,ppc-interrupt-gserver#s", &ilen); |
689 | ireg = get_property(np, "reg", &ilen); | 714 | if (!ireg) |
690 | if (ireg && ireg[0] == get_hard_smp_processor_id(boot_cpuid)) { | 715 | goto skip_gserver_check; |
691 | ireg = get_property(np, | 716 | i = ilen / sizeof(int); |
692 | "ibm,ppc-interrupt-gserver#s", &ilen); | 717 | hcpuid = get_hard_smp_processor_id(boot_cpuid); |
693 | i = ilen / sizeof(int); | 718 | |
694 | if (ireg && i > 0) { | 719 | /* Global interrupt distribution server is specified in the last |
695 | default_server = ireg[0]; | 720 | * entry of "ibm,ppc-interrupt-gserver#s" property. Get the last |
696 | /* take last element */ | 721 | * entry fom this property for current boot cpu id and use it as |
697 | default_distrib_server = ireg[i-1]; | 722 | * default distribution server |
698 | } | 723 | */ |
699 | ireg = get_property(np, | 724 | for (j = 0; j < i; j += 2) { |
725 | if (ireg[j] == hcpuid) { | ||
726 | default_server = hcpuid; | ||
727 | default_distrib_server = ireg[j+1]; | ||
728 | |||
729 | isize = get_property(np, | ||
700 | "ibm,interrupt-server#-size", NULL); | 730 | "ibm,interrupt-server#-size", NULL); |
701 | if (ireg) | 731 | if (isize) |
702 | interrupt_server_size = *ireg; | 732 | interrupt_server_size = *isize; |
703 | break; | ||
704 | } | 733 | } |
705 | } | 734 | } |
735 | skip_gserver_check: | ||
706 | of_node_put(np); | 736 | of_node_put(np); |
707 | 737 | ||
708 | if (firmware_has_feature(FW_FEATURE_LPAR)) | 738 | if (firmware_has_feature(FW_FEATURE_LPAR)) |