diff options
| -rw-r--r-- | arch/powerpc/platforms/cell/Kconfig | 3 | ||||
| -rw-r--r-- | arch/powerpc/platforms/cell/setup.c | 78 | ||||
| -rw-r--r-- | arch/powerpc/platforms/cell/spu_base.c | 72 | ||||
| -rw-r--r-- | mm/memory_hotplug.c | 6 |
4 files changed, 70 insertions, 89 deletions
diff --git a/arch/powerpc/platforms/cell/Kconfig b/arch/powerpc/platforms/cell/Kconfig index c2a3db8edb0c..6a02d51086c8 100644 --- a/arch/powerpc/platforms/cell/Kconfig +++ b/arch/powerpc/platforms/cell/Kconfig | |||
| @@ -12,7 +12,8 @@ config SPU_FS | |||
| 12 | 12 | ||
| 13 | config SPUFS_MMAP | 13 | config SPUFS_MMAP |
| 14 | bool | 14 | bool |
| 15 | depends on SPU_FS && SPARSEMEM && !PPC_64K_PAGES | 15 | depends on SPU_FS && SPARSEMEM |
| 16 | select MEMORY_HOTPLUG | ||
| 16 | default y | 17 | default y |
| 17 | 18 | ||
| 18 | endmenu | 19 | endmenu |
diff --git a/arch/powerpc/platforms/cell/setup.c b/arch/powerpc/platforms/cell/setup.c index dac5d0365fde..6574b22b3cf3 100644 --- a/arch/powerpc/platforms/cell/setup.c +++ b/arch/powerpc/platforms/cell/setup.c | |||
| @@ -29,6 +29,8 @@ | |||
| 29 | #include <linux/seq_file.h> | 29 | #include <linux/seq_file.h> |
| 30 | #include <linux/root_dev.h> | 30 | #include <linux/root_dev.h> |
| 31 | #include <linux/console.h> | 31 | #include <linux/console.h> |
| 32 | #include <linux/mutex.h> | ||
| 33 | #include <linux/memory_hotplug.h> | ||
| 32 | 34 | ||
| 33 | #include <asm/mmu.h> | 35 | #include <asm/mmu.h> |
| 34 | #include <asm/processor.h> | 36 | #include <asm/processor.h> |
| @@ -46,6 +48,7 @@ | |||
| 46 | #include <asm/cputable.h> | 48 | #include <asm/cputable.h> |
| 47 | #include <asm/ppc-pci.h> | 49 | #include <asm/ppc-pci.h> |
| 48 | #include <asm/irq.h> | 50 | #include <asm/irq.h> |
| 51 | #include <asm/spu.h> | ||
| 49 | 52 | ||
| 50 | #include "interrupt.h" | 53 | #include "interrupt.h" |
| 51 | #include "iommu.h" | 54 | #include "iommu.h" |
| @@ -69,77 +72,6 @@ static void cell_show_cpuinfo(struct seq_file *m) | |||
| 69 | of_node_put(root); | 72 | of_node_put(root); |
| 70 | } | 73 | } |
| 71 | 74 | ||
| 72 | #ifdef CONFIG_SPARSEMEM | ||
| 73 | static int __init find_spu_node_id(struct device_node *spe) | ||
| 74 | { | ||
| 75 | unsigned int *id; | ||
| 76 | #ifdef CONFIG_NUMA | ||
| 77 | struct device_node *cpu; | ||
| 78 | cpu = spe->parent->parent; | ||
| 79 | id = (unsigned int *)get_property(cpu, "node-id", NULL); | ||
| 80 | #else | ||
| 81 | id = NULL; | ||
| 82 | #endif | ||
| 83 | return id ? *id : 0; | ||
| 84 | } | ||
| 85 | |||
| 86 | static void __init cell_spuprop_present(struct device_node *spe, | ||
| 87 | const char *prop, int early) | ||
| 88 | { | ||
| 89 | struct address_prop { | ||
| 90 | unsigned long address; | ||
| 91 | unsigned int len; | ||
| 92 | } __attribute__((packed)) *p; | ||
| 93 | int proplen; | ||
| 94 | |||
| 95 | unsigned long start_pfn, end_pfn, pfn; | ||
| 96 | int node_id; | ||
| 97 | |||
| 98 | p = (void*)get_property(spe, prop, &proplen); | ||
| 99 | WARN_ON(proplen != sizeof (*p)); | ||
| 100 | |||
| 101 | node_id = find_spu_node_id(spe); | ||
| 102 | |||
| 103 | start_pfn = p->address >> PAGE_SHIFT; | ||
| 104 | end_pfn = (p->address + p->len + PAGE_SIZE - 1) >> PAGE_SHIFT; | ||
| 105 | |||
| 106 | /* We need to call memory_present *before* the call to sparse_init, | ||
| 107 | but we can initialize the page structs only *after* that call. | ||
| 108 | Thus, we're being called twice. */ | ||
| 109 | if (early) | ||
| 110 | memory_present(node_id, start_pfn, end_pfn); | ||
| 111 | else { | ||
| 112 | /* As the pages backing SPU LS and I/O are outside the range | ||
| 113 | of regular memory, their page structs were not initialized | ||
| 114 | by free_area_init. Do it here instead. */ | ||
| 115 | for (pfn = start_pfn; pfn < end_pfn; pfn++) { | ||
| 116 | struct page *page = pfn_to_page(pfn); | ||
| 117 | set_page_links(page, ZONE_DMA, node_id, pfn); | ||
| 118 | init_page_count(page); | ||
| 119 | reset_page_mapcount(page); | ||
| 120 | SetPageReserved(page); | ||
| 121 | INIT_LIST_HEAD(&page->lru); | ||
| 122 | } | ||
| 123 | } | ||
| 124 | } | ||
| 125 | |||
| 126 | static void __init cell_spumem_init(int early) | ||
| 127 | { | ||
| 128 | struct device_node *node; | ||
| 129 | for (node = of_find_node_by_type(NULL, "spe"); | ||
| 130 | node; node = of_find_node_by_type(node, "spe")) { | ||
| 131 | cell_spuprop_present(node, "local-store", early); | ||
| 132 | cell_spuprop_present(node, "problem", early); | ||
| 133 | cell_spuprop_present(node, "priv1", early); | ||
| 134 | cell_spuprop_present(node, "priv2", early); | ||
| 135 | } | ||
| 136 | } | ||
| 137 | #else | ||
| 138 | static void __init cell_spumem_init(int early) | ||
| 139 | { | ||
| 140 | } | ||
| 141 | #endif | ||
| 142 | |||
| 143 | static void cell_progress(char *s, unsigned short hex) | 75 | static void cell_progress(char *s, unsigned short hex) |
| 144 | { | 76 | { |
| 145 | printk("*** %04x : %s\n", hex, s ? s : ""); | 77 | printk("*** %04x : %s\n", hex, s ? s : ""); |
| @@ -172,8 +104,6 @@ static void __init cell_setup_arch(void) | |||
| 172 | #endif | 104 | #endif |
| 173 | 105 | ||
| 174 | mmio_nvram_init(); | 106 | mmio_nvram_init(); |
| 175 | |||
| 176 | cell_spumem_init(0); | ||
| 177 | } | 107 | } |
| 178 | 108 | ||
| 179 | /* | 109 | /* |
| @@ -189,8 +119,6 @@ static void __init cell_init_early(void) | |||
| 189 | 119 | ||
| 190 | ppc64_interrupt_controller = IC_CELL_PIC; | 120 | ppc64_interrupt_controller = IC_CELL_PIC; |
| 191 | 121 | ||
| 192 | cell_spumem_init(1); | ||
| 193 | |||
| 194 | DBG(" <- cell_init_early()\n"); | 122 | DBG(" <- cell_init_early()\n"); |
| 195 | } | 123 | } |
| 196 | 124 | ||
diff --git a/arch/powerpc/platforms/cell/spu_base.c b/arch/powerpc/platforms/cell/spu_base.c index ef47a6239d48..b788e165c557 100644 --- a/arch/powerpc/platforms/cell/spu_base.c +++ b/arch/powerpc/platforms/cell/spu_base.c | |||
| @@ -520,6 +520,56 @@ void spu_irq_setaffinity(struct spu *spu, int cpu) | |||
| 520 | } | 520 | } |
| 521 | EXPORT_SYMBOL_GPL(spu_irq_setaffinity); | 521 | EXPORT_SYMBOL_GPL(spu_irq_setaffinity); |
| 522 | 522 | ||
| 523 | static int __init find_spu_node_id(struct device_node *spe) | ||
| 524 | { | ||
| 525 | unsigned int *id; | ||
| 526 | struct device_node *cpu; | ||
| 527 | cpu = spe->parent->parent; | ||
| 528 | id = (unsigned int *)get_property(cpu, "node-id", NULL); | ||
| 529 | return id ? *id : 0; | ||
| 530 | } | ||
| 531 | |||
| 532 | static int __init cell_spuprop_present(struct device_node *spe, | ||
| 533 | const char *prop) | ||
| 534 | { | ||
| 535 | static DEFINE_MUTEX(add_spumem_mutex); | ||
| 536 | |||
| 537 | struct address_prop { | ||
| 538 | unsigned long address; | ||
| 539 | unsigned int len; | ||
| 540 | } __attribute__((packed)) *p; | ||
| 541 | int proplen; | ||
| 542 | |||
| 543 | unsigned long start_pfn, nr_pages; | ||
| 544 | int node_id; | ||
| 545 | struct pglist_data *pgdata; | ||
| 546 | struct zone *zone; | ||
| 547 | int ret; | ||
| 548 | |||
| 549 | p = (void*)get_property(spe, prop, &proplen); | ||
| 550 | WARN_ON(proplen != sizeof (*p)); | ||
| 551 | |||
| 552 | start_pfn = p->address >> PAGE_SHIFT; | ||
| 553 | nr_pages = ((unsigned long)p->len + PAGE_SIZE - 1) >> PAGE_SHIFT; | ||
| 554 | |||
| 555 | /* | ||
| 556 | * XXX need to get the correct NUMA node in here. This may | ||
| 557 | * be different from the spe::node_id property, e.g. when | ||
| 558 | * the host firmware is not NUMA aware. | ||
| 559 | */ | ||
| 560 | node_id = 0; | ||
| 561 | |||
| 562 | pgdata = NODE_DATA(node_id); | ||
| 563 | zone = pgdata->node_zones; | ||
| 564 | |||
| 565 | /* XXX rethink locking here */ | ||
| 566 | mutex_lock(&add_spumem_mutex); | ||
| 567 | ret = __add_pages(zone, start_pfn, nr_pages); | ||
| 568 | mutex_unlock(&add_spumem_mutex); | ||
| 569 | |||
| 570 | return ret; | ||
| 571 | } | ||
| 572 | |||
| 523 | static void __iomem * __init map_spe_prop(struct device_node *n, | 573 | static void __iomem * __init map_spe_prop(struct device_node *n, |
| 524 | const char *name) | 574 | const char *name) |
| 525 | { | 575 | { |
| @@ -530,6 +580,8 @@ static void __iomem * __init map_spe_prop(struct device_node *n, | |||
| 530 | 580 | ||
| 531 | void *p; | 581 | void *p; |
| 532 | int proplen; | 582 | int proplen; |
| 583 | void* ret = NULL; | ||
| 584 | int err = 0; | ||
| 533 | 585 | ||
| 534 | p = get_property(n, name, &proplen); | 586 | p = get_property(n, name, &proplen); |
| 535 | if (proplen != sizeof (struct address_prop)) | 587 | if (proplen != sizeof (struct address_prop)) |
| @@ -537,7 +589,14 @@ static void __iomem * __init map_spe_prop(struct device_node *n, | |||
| 537 | 589 | ||
| 538 | prop = p; | 590 | prop = p; |
| 539 | 591 | ||
| 540 | return ioremap(prop->address, prop->len); | 592 | err = cell_spuprop_present(n, name); |
| 593 | if (err && (err != -EEXIST)) | ||
| 594 | goto out; | ||
| 595 | |||
| 596 | ret = ioremap(prop->address, prop->len); | ||
| 597 | |||
| 598 | out: | ||
| 599 | return ret; | ||
| 541 | } | 600 | } |
| 542 | 601 | ||
| 543 | static void spu_unmap(struct spu *spu) | 602 | static void spu_unmap(struct spu *spu) |
| @@ -597,17 +656,6 @@ out: | |||
| 597 | return ret; | 656 | return ret; |
| 598 | } | 657 | } |
| 599 | 658 | ||
| 600 | static int __init find_spu_node_id(struct device_node *spe) | ||
| 601 | { | ||
| 602 | unsigned int *id; | ||
| 603 | struct device_node *cpu; | ||
| 604 | |||
| 605 | cpu = spe->parent->parent; | ||
| 606 | id = (unsigned int *)get_property(cpu, "node-id", NULL); | ||
| 607 | |||
| 608 | return id ? *id : 0; | ||
| 609 | } | ||
| 610 | |||
| 611 | static int __init create_spu(struct device_node *spe) | 659 | static int __init create_spu(struct device_node *spe) |
| 612 | { | 660 | { |
| 613 | struct spu *spu; | 661 | struct spu *spu; |
diff --git a/mm/memory_hotplug.c b/mm/memory_hotplug.c index 1fe76d963ac2..1ae2b2cc3a54 100644 --- a/mm/memory_hotplug.c +++ b/mm/memory_hotplug.c | |||
| @@ -69,12 +69,16 @@ int __add_pages(struct zone *zone, unsigned long phys_start_pfn, | |||
| 69 | for (i = 0; i < nr_pages; i += PAGES_PER_SECTION) { | 69 | for (i = 0; i < nr_pages; i += PAGES_PER_SECTION) { |
| 70 | err = __add_section(zone, phys_start_pfn + i); | 70 | err = __add_section(zone, phys_start_pfn + i); |
| 71 | 71 | ||
| 72 | if (err) | 72 | /* We want to keep adding the rest of the |
| 73 | * sections if the first ones already exist | ||
| 74 | */ | ||
| 75 | if (err && (err != -EEXIST)) | ||
| 73 | break; | 76 | break; |
| 74 | } | 77 | } |
| 75 | 78 | ||
| 76 | return err; | 79 | return err; |
| 77 | } | 80 | } |
| 81 | EXPORT_SYMBOL_GPL(__add_pages); | ||
| 78 | 82 | ||
| 79 | static void grow_zone_span(struct zone *zone, | 83 | static void grow_zone_span(struct zone *zone, |
| 80 | unsigned long start_pfn, unsigned long end_pfn) | 84 | unsigned long start_pfn, unsigned long end_pfn) |
