diff options
author | Linus Torvalds <torvalds@g5.osdl.org> | 2006-11-13 11:20:38 -0500 |
---|---|---|
committer | Linus Torvalds <torvalds@g5.osdl.org> | 2006-11-13 11:20:38 -0500 |
commit | 239fd45938f9ddf64f120e0260c7b76eb73bd5a7 (patch) | |
tree | 2b0350fb9f45f2ffa7473e6c3d75f9ff26d85e82 /arch | |
parent | eea2078eaf2bcd4e5e8b2e08798071efedac5e17 (diff) | |
parent | 36b600f2649e3be49039efe31edeeb64277dbd99 (diff) |
Merge branch 'merge' of git://git.kernel.org/pub/scm/linux/kernel/git/paulus/powerpc
* 'merge' of git://git.kernel.org/pub/scm/linux/kernel/git/paulus/powerpc:
[POWERPC] cell: set ARCH_SPARSEMEM_DEFAULT in Kconfig
[POWERPC] Fix cell "new style" mapping and add debug
[POWERPC] pseries: Force 4k update_flash block and list sizes
[POWERPC] CPM_UART: Fix non-console initialisation
[POWERPC] CPM_UART: Fix non-console transmit
[POWERPC] Make sure initrd and dtb sections get into zImage correctly
Diffstat (limited to 'arch')
-rw-r--r-- | arch/powerpc/Kconfig | 2 | ||||
-rwxr-xr-x | arch/powerpc/boot/wrapper | 4 | ||||
-rw-r--r-- | arch/powerpc/boot/zImage.lds.S | 5 | ||||
-rw-r--r-- | arch/powerpc/kernel/rtas_flash.c | 47 | ||||
-rw-r--r-- | arch/powerpc/platforms/cell/spu_base.c | 41 |
5 files changed, 78 insertions, 21 deletions
diff --git a/arch/powerpc/Kconfig b/arch/powerpc/Kconfig index 2bd9b7fb0f6c..0673dbedb241 100644 --- a/arch/powerpc/Kconfig +++ b/arch/powerpc/Kconfig | |||
@@ -740,7 +740,7 @@ config ARCH_SPARSEMEM_ENABLE | |||
740 | 740 | ||
741 | config ARCH_SPARSEMEM_DEFAULT | 741 | config ARCH_SPARSEMEM_DEFAULT |
742 | def_bool y | 742 | def_bool y |
743 | depends on SMP && PPC_PSERIES | 743 | depends on (SMP && PPC_PSERIES) || PPC_CELL |
744 | 744 | ||
745 | config ARCH_POPULATES_NODE_MAP | 745 | config ARCH_POPULATES_NODE_MAP |
746 | def_bool y | 746 | def_bool y |
diff --git a/arch/powerpc/boot/wrapper b/arch/powerpc/boot/wrapper index eab7318729e9..b5fb1fee76f8 100755 --- a/arch/powerpc/boot/wrapper +++ b/arch/powerpc/boot/wrapper | |||
@@ -179,11 +179,11 @@ if [ -z "$cacheit" ]; then | |||
179 | fi | 179 | fi |
180 | 180 | ||
181 | if [ -n "$initrd" ]; then | 181 | if [ -n "$initrd" ]; then |
182 | addsec $tmp "$initrd" initrd | 182 | addsec $tmp "$initrd" $isection |
183 | fi | 183 | fi |
184 | 184 | ||
185 | if [ -n "$dtb" ]; then | 185 | if [ -n "$dtb" ]; then |
186 | addsec $tmp "$dtb" dtb | 186 | addsec $tmp "$dtb" .kernel:dtb |
187 | fi | 187 | fi |
188 | 188 | ||
189 | if [ "$platform" != "miboot" ]; then | 189 | if [ "$platform" != "miboot" ]; then |
diff --git a/arch/powerpc/boot/zImage.lds.S b/arch/powerpc/boot/zImage.lds.S index 4b6bb3ffe3dc..4be3c6414b04 100644 --- a/arch/powerpc/boot/zImage.lds.S +++ b/arch/powerpc/boot/zImage.lds.S | |||
@@ -21,6 +21,11 @@ SECTIONS | |||
21 | __got2_end = .; | 21 | __got2_end = .; |
22 | } | 22 | } |
23 | 23 | ||
24 | . = ALIGN(8); | ||
25 | _dtb_start = .; | ||
26 | .kernel:dtb : { *(.kernel:dtb) } | ||
27 | _dtb_end = .; | ||
28 | |||
24 | . = ALIGN(4096); | 29 | . = ALIGN(4096); |
25 | _vmlinux_start = .; | 30 | _vmlinux_start = .; |
26 | .kernel:vmlinux.strip : { *(.kernel:vmlinux.strip) } | 31 | .kernel:vmlinux.strip : { *(.kernel:vmlinux.strip) } |
diff --git a/arch/powerpc/kernel/rtas_flash.c b/arch/powerpc/kernel/rtas_flash.c index 1442b63a75da..6f6fc977cb39 100644 --- a/arch/powerpc/kernel/rtas_flash.c +++ b/arch/powerpc/kernel/rtas_flash.c | |||
@@ -72,6 +72,10 @@ | |||
72 | #define VALIDATE_BUF_SIZE 4096 | 72 | #define VALIDATE_BUF_SIZE 4096 |
73 | #define RTAS_MSG_MAXLEN 64 | 73 | #define RTAS_MSG_MAXLEN 64 |
74 | 74 | ||
75 | /* Quirk - RTAS requires 4k list length and block size */ | ||
76 | #define RTAS_BLKLIST_LENGTH 4096 | ||
77 | #define RTAS_BLK_SIZE 4096 | ||
78 | |||
75 | struct flash_block { | 79 | struct flash_block { |
76 | char *data; | 80 | char *data; |
77 | unsigned long length; | 81 | unsigned long length; |
@@ -83,7 +87,7 @@ struct flash_block { | |||
83 | * into a version/length and translate the pointers | 87 | * into a version/length and translate the pointers |
84 | * to absolute. | 88 | * to absolute. |
85 | */ | 89 | */ |
86 | #define FLASH_BLOCKS_PER_NODE ((PAGE_SIZE - 16) / sizeof(struct flash_block)) | 90 | #define FLASH_BLOCKS_PER_NODE ((RTAS_BLKLIST_LENGTH - 16) / sizeof(struct flash_block)) |
87 | struct flash_block_list { | 91 | struct flash_block_list { |
88 | unsigned long num_blocks; | 92 | unsigned long num_blocks; |
89 | struct flash_block_list *next; | 93 | struct flash_block_list *next; |
@@ -96,6 +100,9 @@ struct flash_block_list_header { /* just the header of flash_block_list */ | |||
96 | 100 | ||
97 | static struct flash_block_list_header rtas_firmware_flash_list = {0, NULL}; | 101 | static struct flash_block_list_header rtas_firmware_flash_list = {0, NULL}; |
98 | 102 | ||
103 | /* Use slab cache to guarantee 4k alignment */ | ||
104 | static kmem_cache_t *flash_block_cache = NULL; | ||
105 | |||
99 | #define FLASH_BLOCK_LIST_VERSION (1UL) | 106 | #define FLASH_BLOCK_LIST_VERSION (1UL) |
100 | 107 | ||
101 | /* Local copy of the flash block list. | 108 | /* Local copy of the flash block list. |
@@ -153,7 +160,7 @@ static int flash_list_valid(struct flash_block_list *flist) | |||
153 | return FLASH_IMG_NULL_DATA; | 160 | return FLASH_IMG_NULL_DATA; |
154 | } | 161 | } |
155 | block_size = f->blocks[i].length; | 162 | block_size = f->blocks[i].length; |
156 | if (block_size <= 0 || block_size > PAGE_SIZE) { | 163 | if (block_size <= 0 || block_size > RTAS_BLK_SIZE) { |
157 | return FLASH_IMG_BAD_LEN; | 164 | return FLASH_IMG_BAD_LEN; |
158 | } | 165 | } |
159 | image_size += block_size; | 166 | image_size += block_size; |
@@ -177,9 +184,9 @@ static void free_flash_list(struct flash_block_list *f) | |||
177 | 184 | ||
178 | while (f) { | 185 | while (f) { |
179 | for (i = 0; i < f->num_blocks; i++) | 186 | for (i = 0; i < f->num_blocks; i++) |
180 | free_page((unsigned long)(f->blocks[i].data)); | 187 | kmem_cache_free(flash_block_cache, f->blocks[i].data); |
181 | next = f->next; | 188 | next = f->next; |
182 | free_page((unsigned long)f); | 189 | kmem_cache_free(flash_block_cache, f); |
183 | f = next; | 190 | f = next; |
184 | } | 191 | } |
185 | } | 192 | } |
@@ -278,6 +285,12 @@ static ssize_t rtas_flash_read(struct file *file, char __user *buf, | |||
278 | return msglen; | 285 | return msglen; |
279 | } | 286 | } |
280 | 287 | ||
288 | /* constructor for flash_block_cache */ | ||
289 | void rtas_block_ctor(void *ptr, kmem_cache_t *cache, unsigned long flags) | ||
290 | { | ||
291 | memset(ptr, 0, RTAS_BLK_SIZE); | ||
292 | } | ||
293 | |||
281 | /* We could be much more efficient here. But to keep this function | 294 | /* We could be much more efficient here. But to keep this function |
282 | * simple we allocate a page to the block list no matter how small the | 295 | * simple we allocate a page to the block list no matter how small the |
283 | * count is. If the system is low on memory it will be just as well | 296 | * count is. If the system is low on memory it will be just as well |
@@ -302,7 +315,7 @@ static ssize_t rtas_flash_write(struct file *file, const char __user *buffer, | |||
302 | * proc file | 315 | * proc file |
303 | */ | 316 | */ |
304 | if (uf->flist == NULL) { | 317 | if (uf->flist == NULL) { |
305 | uf->flist = (struct flash_block_list *) get_zeroed_page(GFP_KERNEL); | 318 | uf->flist = kmem_cache_alloc(flash_block_cache, GFP_KERNEL); |
306 | if (!uf->flist) | 319 | if (!uf->flist) |
307 | return -ENOMEM; | 320 | return -ENOMEM; |
308 | } | 321 | } |
@@ -313,21 +326,21 @@ static ssize_t rtas_flash_write(struct file *file, const char __user *buffer, | |||
313 | next_free = fl->num_blocks; | 326 | next_free = fl->num_blocks; |
314 | if (next_free == FLASH_BLOCKS_PER_NODE) { | 327 | if (next_free == FLASH_BLOCKS_PER_NODE) { |
315 | /* Need to allocate another block_list */ | 328 | /* Need to allocate another block_list */ |
316 | fl->next = (struct flash_block_list *)get_zeroed_page(GFP_KERNEL); | 329 | fl->next = kmem_cache_alloc(flash_block_cache, GFP_KERNEL); |
317 | if (!fl->next) | 330 | if (!fl->next) |
318 | return -ENOMEM; | 331 | return -ENOMEM; |
319 | fl = fl->next; | 332 | fl = fl->next; |
320 | next_free = 0; | 333 | next_free = 0; |
321 | } | 334 | } |
322 | 335 | ||
323 | if (count > PAGE_SIZE) | 336 | if (count > RTAS_BLK_SIZE) |
324 | count = PAGE_SIZE; | 337 | count = RTAS_BLK_SIZE; |
325 | p = (char *)get_zeroed_page(GFP_KERNEL); | 338 | p = kmem_cache_alloc(flash_block_cache, GFP_KERNEL); |
326 | if (!p) | 339 | if (!p) |
327 | return -ENOMEM; | 340 | return -ENOMEM; |
328 | 341 | ||
329 | if(copy_from_user(p, buffer, count)) { | 342 | if(copy_from_user(p, buffer, count)) { |
330 | free_page((unsigned long)p); | 343 | kmem_cache_free(flash_block_cache, p); |
331 | return -EFAULT; | 344 | return -EFAULT; |
332 | } | 345 | } |
333 | fl->blocks[next_free].data = p; | 346 | fl->blocks[next_free].data = p; |
@@ -791,6 +804,16 @@ int __init rtas_flash_init(void) | |||
791 | goto cleanup; | 804 | goto cleanup; |
792 | 805 | ||
793 | rtas_flash_term_hook = rtas_flash_firmware; | 806 | rtas_flash_term_hook = rtas_flash_firmware; |
807 | |||
808 | flash_block_cache = kmem_cache_create("rtas_flash_cache", | ||
809 | RTAS_BLK_SIZE, RTAS_BLK_SIZE, 0, | ||
810 | rtas_block_ctor, NULL); | ||
811 | if (!flash_block_cache) { | ||
812 | printk(KERN_ERR "%s: failed to create block cache\n", | ||
813 | __FUNCTION__); | ||
814 | rc = -ENOMEM; | ||
815 | goto cleanup; | ||
816 | } | ||
794 | return 0; | 817 | return 0; |
795 | 818 | ||
796 | cleanup: | 819 | cleanup: |
@@ -805,6 +828,10 @@ cleanup: | |||
805 | void __exit rtas_flash_cleanup(void) | 828 | void __exit rtas_flash_cleanup(void) |
806 | { | 829 | { |
807 | rtas_flash_term_hook = NULL; | 830 | rtas_flash_term_hook = NULL; |
831 | |||
832 | if (flash_block_cache) | ||
833 | kmem_cache_destroy(flash_block_cache); | ||
834 | |||
808 | remove_flash_pde(firmware_flash_pde); | 835 | remove_flash_pde(firmware_flash_pde); |
809 | remove_flash_pde(firmware_update_pde); | 836 | remove_flash_pde(firmware_update_pde); |
810 | remove_flash_pde(validate_pde); | 837 | remove_flash_pde(validate_pde); |
diff --git a/arch/powerpc/platforms/cell/spu_base.c b/arch/powerpc/platforms/cell/spu_base.c index d0fb959e3ef1..7aa809d5a244 100644 --- a/arch/powerpc/platforms/cell/spu_base.c +++ b/arch/powerpc/platforms/cell/spu_base.c | |||
@@ -655,14 +655,19 @@ static int __init spu_map_interrupts(struct spu *spu, struct device_node *np) | |||
655 | 655 | ||
656 | for (i=0; i < 3; i++) { | 656 | for (i=0; i < 3; i++) { |
657 | ret = of_irq_map_one(np, i, &oirq); | 657 | ret = of_irq_map_one(np, i, &oirq); |
658 | if (ret) | 658 | if (ret) { |
659 | pr_debug("spu_new: failed to get irq %d\n", i); | ||
659 | goto err; | 660 | goto err; |
660 | 661 | } | |
661 | ret = -EINVAL; | 662 | ret = -EINVAL; |
663 | pr_debug(" irq %d no 0x%x on %s\n", i, oirq.specifier[0], | ||
664 | oirq.controller->full_name); | ||
662 | spu->irqs[i] = irq_create_of_mapping(oirq.controller, | 665 | spu->irqs[i] = irq_create_of_mapping(oirq.controller, |
663 | oirq.specifier, oirq.size); | 666 | oirq.specifier, oirq.size); |
664 | if (spu->irqs[i] == NO_IRQ) | 667 | if (spu->irqs[i] == NO_IRQ) { |
668 | pr_debug("spu_new: failed to map it !\n"); | ||
665 | goto err; | 669 | goto err; |
670 | } | ||
666 | } | 671 | } |
667 | return 0; | 672 | return 0; |
668 | 673 | ||
@@ -681,7 +686,7 @@ static int spu_map_resource(struct device_node *node, int nr, | |||
681 | struct resource resource = { }; | 686 | struct resource resource = { }; |
682 | int ret; | 687 | int ret; |
683 | 688 | ||
684 | ret = of_address_to_resource(node, 0, &resource); | 689 | ret = of_address_to_resource(node, nr, &resource); |
685 | if (ret) | 690 | if (ret) |
686 | goto out; | 691 | goto out; |
687 | 692 | ||
@@ -704,22 +709,42 @@ static int __init spu_map_device(struct spu *spu, struct device_node *node) | |||
704 | 709 | ||
705 | ret = spu_map_resource(node, 0, (void __iomem**)&spu->local_store, | 710 | ret = spu_map_resource(node, 0, (void __iomem**)&spu->local_store, |
706 | &spu->local_store_phys); | 711 | &spu->local_store_phys); |
707 | if (ret) | 712 | if (ret) { |
713 | pr_debug("spu_new: failed to map %s resource 0\n", | ||
714 | node->full_name); | ||
708 | goto out; | 715 | goto out; |
716 | } | ||
709 | ret = spu_map_resource(node, 1, (void __iomem**)&spu->problem, | 717 | ret = spu_map_resource(node, 1, (void __iomem**)&spu->problem, |
710 | &spu->problem_phys); | 718 | &spu->problem_phys); |
711 | if (ret) | 719 | if (ret) { |
720 | pr_debug("spu_new: failed to map %s resource 1\n", | ||
721 | node->full_name); | ||
712 | goto out_unmap; | 722 | goto out_unmap; |
723 | } | ||
713 | ret = spu_map_resource(node, 2, (void __iomem**)&spu->priv2, | 724 | ret = spu_map_resource(node, 2, (void __iomem**)&spu->priv2, |
714 | NULL); | 725 | NULL); |
715 | if (ret) | 726 | if (ret) { |
727 | pr_debug("spu_new: failed to map %s resource 2\n", | ||
728 | node->full_name); | ||
716 | goto out_unmap; | 729 | goto out_unmap; |
730 | } | ||
717 | 731 | ||
718 | if (!firmware_has_feature(FW_FEATURE_LPAR)) | 732 | if (!firmware_has_feature(FW_FEATURE_LPAR)) |
719 | ret = spu_map_resource(node, 3, (void __iomem**)&spu->priv1, | 733 | ret = spu_map_resource(node, 3, (void __iomem**)&spu->priv1, |
720 | NULL); | 734 | NULL); |
721 | if (ret) | 735 | if (ret) { |
736 | pr_debug("spu_new: failed to map %s resource 3\n", | ||
737 | node->full_name); | ||
722 | goto out_unmap; | 738 | goto out_unmap; |
739 | } | ||
740 | pr_debug("spu_new: %s maps:\n", node->full_name); | ||
741 | pr_debug(" local store : 0x%016lx -> 0x%p\n", | ||
742 | spu->local_store_phys, spu->local_store); | ||
743 | pr_debug(" problem state : 0x%016lx -> 0x%p\n", | ||
744 | spu->problem_phys, spu->problem); | ||
745 | pr_debug(" priv2 : 0x%p\n", spu->priv2); | ||
746 | pr_debug(" priv1 : 0x%p\n", spu->priv1); | ||
747 | |||
723 | return 0; | 748 | return 0; |
724 | 749 | ||
725 | out_unmap: | 750 | out_unmap: |