diff options
Diffstat (limited to 'arch/powerpc')
-rw-r--r-- | arch/powerpc/Kconfig | 6 | ||||
-rw-r--r-- | arch/powerpc/mm/mem.c | 33 | ||||
-rw-r--r-- | arch/powerpc/mm/pgtable_32.c | 14 | ||||
-rw-r--r-- | arch/powerpc/platforms/cell/iommu.c | 48 | ||||
-rw-r--r-- | arch/powerpc/platforms/cell/spufs/backing_ops.c | 6 | ||||
-rw-r--r-- | arch/powerpc/platforms/cell/spufs/fault.c | 12 | ||||
-rw-r--r-- | arch/powerpc/platforms/cell/spufs/file.c | 57 | ||||
-rw-r--r-- | arch/powerpc/platforms/cell/spufs/inode.c | 3 | ||||
-rw-r--r-- | arch/powerpc/platforms/cell/spufs/run.c | 21 | ||||
-rw-r--r-- | arch/powerpc/platforms/cell/spufs/spufs.h | 5 | ||||
-rw-r--r-- | arch/powerpc/platforms/powermac/feature.c | 11 |
11 files changed, 148 insertions, 68 deletions
diff --git a/arch/powerpc/Kconfig b/arch/powerpc/Kconfig index 8dcac0b22d68..26b963c33c88 100644 --- a/arch/powerpc/Kconfig +++ b/arch/powerpc/Kconfig | |||
@@ -272,6 +272,12 @@ config HOTPLUG_CPU | |||
272 | config ARCH_ENABLE_MEMORY_HOTPLUG | 272 | config ARCH_ENABLE_MEMORY_HOTPLUG |
273 | def_bool y | 273 | def_bool y |
274 | 274 | ||
275 | config ARCH_HAS_WALK_MEMORY | ||
276 | def_bool y | ||
277 | |||
278 | config ARCH_ENABLE_MEMORY_HOTREMOVE | ||
279 | def_bool y | ||
280 | |||
275 | config KEXEC | 281 | config KEXEC |
276 | bool "kexec system call (EXPERIMENTAL)" | 282 | bool "kexec system call (EXPERIMENTAL)" |
277 | depends on (PPC_PRPMC2800 || PPC_MULTIPLATFORM) && EXPERIMENTAL | 283 | depends on (PPC_PRPMC2800 || PPC_MULTIPLATFORM) && EXPERIMENTAL |
diff --git a/arch/powerpc/mm/mem.c b/arch/powerpc/mm/mem.c index 93a5c53e3423..be5c506779a7 100644 --- a/arch/powerpc/mm/mem.c +++ b/arch/powerpc/mm/mem.c | |||
@@ -129,6 +129,39 @@ int __devinit arch_add_memory(int nid, u64 start, u64 size) | |||
129 | return __add_pages(zone, start_pfn, nr_pages); | 129 | return __add_pages(zone, start_pfn, nr_pages); |
130 | } | 130 | } |
131 | 131 | ||
132 | #ifdef CONFIG_MEMORY_HOTREMOVE | ||
133 | int remove_memory(u64 start, u64 size) | ||
134 | { | ||
135 | unsigned long start_pfn, end_pfn; | ||
136 | int ret; | ||
137 | |||
138 | start_pfn = start >> PAGE_SHIFT; | ||
139 | end_pfn = start_pfn + (size >> PAGE_SHIFT); | ||
140 | ret = offline_pages(start_pfn, end_pfn, 120 * HZ); | ||
141 | if (ret) | ||
142 | goto out; | ||
143 | /* Arch-specific calls go here - next patch */ | ||
144 | out: | ||
145 | return ret; | ||
146 | } | ||
147 | #endif /* CONFIG_MEMORY_HOTREMOVE */ | ||
148 | |||
149 | /* | ||
150 | * walk_memory_resource() needs to make sure there is no holes in a given | ||
151 | * memory range. On PPC64, since this range comes from /sysfs, the range | ||
152 | * is guaranteed to be valid, non-overlapping and can not contain any | ||
153 | * holes. By the time we get here (memory add or remove), /proc/device-tree | ||
154 | * is updated and correct. Only reason we need to check against device-tree | ||
155 | * would be if we allow user-land to specify a memory range through a | ||
156 | * system call/ioctl etc. instead of doing offline/online through /sysfs. | ||
157 | */ | ||
158 | int | ||
159 | walk_memory_resource(unsigned long start_pfn, unsigned long nr_pages, void *arg, | ||
160 | int (*func)(unsigned long, unsigned long, void *)) | ||
161 | { | ||
162 | return (*func)(start_pfn, nr_pages, arg); | ||
163 | } | ||
164 | |||
132 | #endif /* CONFIG_MEMORY_HOTPLUG */ | 165 | #endif /* CONFIG_MEMORY_HOTPLUG */ |
133 | 166 | ||
134 | void show_mem(void) | 167 | void show_mem(void) |
diff --git a/arch/powerpc/mm/pgtable_32.c b/arch/powerpc/mm/pgtable_32.c index f80f90c4d58b..ac3390f81900 100644 --- a/arch/powerpc/mm/pgtable_32.c +++ b/arch/powerpc/mm/pgtable_32.c | |||
@@ -107,19 +107,20 @@ __init_refok pte_t *pte_alloc_one_kernel(struct mm_struct *mm, unsigned long add | |||
107 | return pte; | 107 | return pte; |
108 | } | 108 | } |
109 | 109 | ||
110 | struct page *pte_alloc_one(struct mm_struct *mm, unsigned long address) | 110 | pgtable_t pte_alloc_one(struct mm_struct *mm, unsigned long address) |
111 | { | 111 | { |
112 | struct page *ptepage; | 112 | struct page *ptepage; |
113 | 113 | ||
114 | #ifdef CONFIG_HIGHPTE | 114 | #ifdef CONFIG_HIGHPTE |
115 | gfp_t flags = GFP_KERNEL | __GFP_HIGHMEM | __GFP_REPEAT; | 115 | gfp_t flags = GFP_KERNEL | __GFP_HIGHMEM | __GFP_REPEAT | __GFP_ZERO; |
116 | #else | 116 | #else |
117 | gfp_t flags = GFP_KERNEL | __GFP_REPEAT; | 117 | gfp_t flags = GFP_KERNEL | __GFP_REPEAT | __GFP_ZERO; |
118 | #endif | 118 | #endif |
119 | 119 | ||
120 | ptepage = alloc_pages(flags, 0); | 120 | ptepage = alloc_pages(flags, 0); |
121 | if (ptepage) | 121 | if (!ptepage) |
122 | clear_highpage(ptepage); | 122 | return NULL; |
123 | pgtable_page_ctor(ptepage); | ||
123 | return ptepage; | 124 | return ptepage; |
124 | } | 125 | } |
125 | 126 | ||
@@ -131,11 +132,12 @@ void pte_free_kernel(struct mm_struct *mm, pte_t *pte) | |||
131 | free_page((unsigned long)pte); | 132 | free_page((unsigned long)pte); |
132 | } | 133 | } |
133 | 134 | ||
134 | void pte_free(struct mm_struct *mm, struct page *ptepage) | 135 | void pte_free(struct mm_struct *mm, pgtable_t ptepage) |
135 | { | 136 | { |
136 | #ifdef CONFIG_SMP | 137 | #ifdef CONFIG_SMP |
137 | hash_page_sync(); | 138 | hash_page_sync(); |
138 | #endif | 139 | #endif |
140 | pgtable_page_dtor(ptepage); | ||
139 | __free_page(ptepage); | 141 | __free_page(ptepage); |
140 | } | 142 | } |
141 | 143 | ||
diff --git a/arch/powerpc/platforms/cell/iommu.c b/arch/powerpc/platforms/cell/iommu.c index df330666ccc9..edab631a8dcb 100644 --- a/arch/powerpc/platforms/cell/iommu.c +++ b/arch/powerpc/platforms/cell/iommu.c | |||
@@ -26,6 +26,7 @@ | |||
26 | #include <linux/init.h> | 26 | #include <linux/init.h> |
27 | #include <linux/interrupt.h> | 27 | #include <linux/interrupt.h> |
28 | #include <linux/notifier.h> | 28 | #include <linux/notifier.h> |
29 | #include <linux/of.h> | ||
29 | #include <linux/of_platform.h> | 30 | #include <linux/of_platform.h> |
30 | 31 | ||
31 | #include <asm/prom.h> | 32 | #include <asm/prom.h> |
@@ -789,18 +790,16 @@ static int __init cell_iommu_init_disabled(void) | |||
789 | static u64 cell_iommu_get_fixed_address(struct device *dev) | 790 | static u64 cell_iommu_get_fixed_address(struct device *dev) |
790 | { | 791 | { |
791 | u64 cpu_addr, size, best_size, pci_addr = OF_BAD_ADDR; | 792 | u64 cpu_addr, size, best_size, pci_addr = OF_BAD_ADDR; |
792 | struct device_node *tmp, *np; | 793 | struct device_node *np; |
793 | const u32 *ranges = NULL; | 794 | const u32 *ranges = NULL; |
794 | int i, len, best; | 795 | int i, len, best; |
795 | 796 | ||
796 | np = dev->archdata.of_node; | 797 | np = of_node_get(dev->archdata.of_node); |
797 | of_node_get(np); | 798 | while (np) { |
798 | ranges = of_get_property(np, "dma-ranges", &len); | ||
799 | while (!ranges && np) { | ||
800 | tmp = of_get_parent(np); | ||
801 | of_node_put(np); | ||
802 | np = tmp; | ||
803 | ranges = of_get_property(np, "dma-ranges", &len); | 799 | ranges = of_get_property(np, "dma-ranges", &len); |
800 | if (ranges) | ||
801 | break; | ||
802 | np = of_get_next_parent(np); | ||
804 | } | 803 | } |
805 | 804 | ||
806 | if (!ranges) { | 805 | if (!ranges) { |
@@ -842,19 +841,18 @@ static int dma_set_mask_and_switch(struct device *dev, u64 dma_mask) | |||
842 | if (!dev->dma_mask || !dma_supported(dev, dma_mask)) | 841 | if (!dev->dma_mask || !dma_supported(dev, dma_mask)) |
843 | return -EIO; | 842 | return -EIO; |
844 | 843 | ||
845 | if (dma_mask == DMA_BIT_MASK(64)) { | 844 | if (dma_mask == DMA_BIT_MASK(64) && |
846 | if (cell_iommu_get_fixed_address(dev) == OF_BAD_ADDR) | 845 | cell_iommu_get_fixed_address(dev) != OF_BAD_ADDR) |
847 | dev_dbg(dev, "iommu: 64-bit OK, but bad addr\n"); | 846 | { |
848 | else { | 847 | dev_dbg(dev, "iommu: 64-bit OK, using fixed ops\n"); |
849 | dev_dbg(dev, "iommu: 64-bit OK, using fixed ops\n"); | 848 | set_dma_ops(dev, &dma_iommu_fixed_ops); |
850 | set_dma_ops(dev, &dma_iommu_fixed_ops); | ||
851 | cell_dma_dev_setup(dev); | ||
852 | } | ||
853 | } else { | 849 | } else { |
854 | dev_dbg(dev, "iommu: not 64-bit, using default ops\n"); | 850 | dev_dbg(dev, "iommu: not 64-bit, using default ops\n"); |
855 | set_dma_ops(dev, get_pci_dma_ops()); | 851 | set_dma_ops(dev, get_pci_dma_ops()); |
856 | } | 852 | } |
857 | 853 | ||
854 | cell_dma_dev_setup(dev); | ||
855 | |||
858 | *dev->dma_mask = dma_mask; | 856 | *dev->dma_mask = dma_mask; |
859 | 857 | ||
860 | return 0; | 858 | return 0; |
@@ -918,6 +916,18 @@ static int __init cell_iommu_fixed_mapping_init(void) | |||
918 | return -1; | 916 | return -1; |
919 | } | 917 | } |
920 | 918 | ||
919 | /* We must have dma-ranges properties for fixed mapping to work */ | ||
920 | for (np = NULL; (np = of_find_all_nodes(np));) { | ||
921 | if (of_find_property(np, "dma-ranges", NULL)) | ||
922 | break; | ||
923 | } | ||
924 | of_node_put(np); | ||
925 | |||
926 | if (!np) { | ||
927 | pr_debug("iommu: no dma-ranges found, no fixed mapping\n"); | ||
928 | return -1; | ||
929 | } | ||
930 | |||
921 | /* The default setup is to have the fixed mapping sit after the | 931 | /* The default setup is to have the fixed mapping sit after the |
922 | * dynamic region, so find the top of the largest IOMMU window | 932 | * dynamic region, so find the top of the largest IOMMU window |
923 | * on any axon, then add the size of RAM and that's our max value. | 933 | * on any axon, then add the size of RAM and that's our max value. |
@@ -981,8 +991,8 @@ static int __init cell_iommu_fixed_mapping_init(void) | |||
981 | dsize = htab_size_bytes; | 991 | dsize = htab_size_bytes; |
982 | } | 992 | } |
983 | 993 | ||
984 | pr_debug("iommu: setting up %d, dynamic window %lx-%lx " \ | 994 | printk(KERN_DEBUG "iommu: node %d, dynamic window 0x%lx-0x%lx " |
985 | "fixed window %lx-%lx\n", iommu->nid, dbase, | 995 | "fixed window 0x%lx-0x%lx\n", iommu->nid, dbase, |
986 | dbase + dsize, fbase, fbase + fsize); | 996 | dbase + dsize, fbase, fbase + fsize); |
987 | 997 | ||
988 | cell_iommu_setup_page_tables(iommu, dbase, dsize, fbase, fsize); | 998 | cell_iommu_setup_page_tables(iommu, dbase, dsize, fbase, fsize); |
@@ -998,8 +1008,6 @@ static int __init cell_iommu_fixed_mapping_init(void) | |||
998 | dma_iommu_ops.set_dma_mask = dma_set_mask_and_switch; | 1008 | dma_iommu_ops.set_dma_mask = dma_set_mask_and_switch; |
999 | set_pci_dma_ops(&dma_iommu_ops); | 1009 | set_pci_dma_ops(&dma_iommu_ops); |
1000 | 1010 | ||
1001 | printk(KERN_DEBUG "IOMMU fixed mapping established.\n"); | ||
1002 | |||
1003 | return 0; | 1011 | return 0; |
1004 | } | 1012 | } |
1005 | 1013 | ||
diff --git a/arch/powerpc/platforms/cell/spufs/backing_ops.c b/arch/powerpc/platforms/cell/spufs/backing_ops.c index 50d98a154aaf..64eb15b22040 100644 --- a/arch/powerpc/platforms/cell/spufs/backing_ops.c +++ b/arch/powerpc/platforms/cell/spufs/backing_ops.c | |||
@@ -288,6 +288,12 @@ static void spu_backing_runcntl_write(struct spu_context *ctx, u32 val) | |||
288 | spin_lock(&ctx->csa.register_lock); | 288 | spin_lock(&ctx->csa.register_lock); |
289 | ctx->csa.prob.spu_runcntl_RW = val; | 289 | ctx->csa.prob.spu_runcntl_RW = val; |
290 | if (val & SPU_RUNCNTL_RUNNABLE) { | 290 | if (val & SPU_RUNCNTL_RUNNABLE) { |
291 | ctx->csa.prob.spu_status_R &= | ||
292 | ~SPU_STATUS_STOPPED_BY_STOP & | ||
293 | ~SPU_STATUS_STOPPED_BY_HALT & | ||
294 | ~SPU_STATUS_SINGLE_STEP & | ||
295 | ~SPU_STATUS_INVALID_INSTR & | ||
296 | ~SPU_STATUS_INVALID_CH; | ||
291 | ctx->csa.prob.spu_status_R |= SPU_STATUS_RUNNING; | 297 | ctx->csa.prob.spu_status_R |= SPU_STATUS_RUNNING; |
292 | } else { | 298 | } else { |
293 | ctx->csa.prob.spu_status_R &= ~SPU_STATUS_RUNNING; | 299 | ctx->csa.prob.spu_status_R &= ~SPU_STATUS_RUNNING; |
diff --git a/arch/powerpc/platforms/cell/spufs/fault.c b/arch/powerpc/platforms/cell/spufs/fault.c index eff4d291ba85..e46d300e21a5 100644 --- a/arch/powerpc/platforms/cell/spufs/fault.c +++ b/arch/powerpc/platforms/cell/spufs/fault.c | |||
@@ -108,7 +108,7 @@ int spufs_handle_class1(struct spu_context *ctx) | |||
108 | u64 ea, dsisr, access; | 108 | u64 ea, dsisr, access; |
109 | unsigned long flags; | 109 | unsigned long flags; |
110 | unsigned flt = 0; | 110 | unsigned flt = 0; |
111 | int ret, ret2; | 111 | int ret; |
112 | 112 | ||
113 | /* | 113 | /* |
114 | * dar and dsisr get passed from the registers | 114 | * dar and dsisr get passed from the registers |
@@ -148,13 +148,10 @@ int spufs_handle_class1(struct spu_context *ctx) | |||
148 | ret = spu_handle_mm_fault(current->mm, ea, dsisr, &flt); | 148 | ret = spu_handle_mm_fault(current->mm, ea, dsisr, &flt); |
149 | 149 | ||
150 | /* | 150 | /* |
151 | * If spu_acquire fails due to a pending signal we just want to return | 151 | * This is nasty: we need the state_mutex for all the bookkeeping even |
152 | * EINTR to userspace even if that means missing the dma restart or | 152 | * if the syscall was interrupted by a signal. ewww. |
153 | * updating the page fault statistics. | ||
154 | */ | 153 | */ |
155 | ret2 = spu_acquire(ctx); | 154 | mutex_lock(&ctx->state_mutex); |
156 | if (ret2) | ||
157 | goto out; | ||
158 | 155 | ||
159 | /* | 156 | /* |
160 | * Clear dsisr under ctxt lock after handling the fault, so that | 157 | * Clear dsisr under ctxt lock after handling the fault, so that |
@@ -185,7 +182,6 @@ int spufs_handle_class1(struct spu_context *ctx) | |||
185 | } else | 182 | } else |
186 | spufs_handle_event(ctx, ea, SPE_EVENT_SPE_DATA_STORAGE); | 183 | spufs_handle_event(ctx, ea, SPE_EVENT_SPE_DATA_STORAGE); |
187 | 184 | ||
188 | out: | ||
189 | spuctx_switch_state(ctx, SPU_UTIL_SYSTEM); | 185 | spuctx_switch_state(ctx, SPU_UTIL_SYSTEM); |
190 | return ret; | 186 | return ret; |
191 | } | 187 | } |
diff --git a/arch/powerpc/platforms/cell/spufs/file.c b/arch/powerpc/platforms/cell/spufs/file.c index 1018acd1746b..c66c3756970d 100644 --- a/arch/powerpc/platforms/cell/spufs/file.c +++ b/arch/powerpc/platforms/cell/spufs/file.c | |||
@@ -358,6 +358,7 @@ static unsigned long spufs_ps_nopfn(struct vm_area_struct *vma, | |||
358 | { | 358 | { |
359 | struct spu_context *ctx = vma->vm_file->private_data; | 359 | struct spu_context *ctx = vma->vm_file->private_data; |
360 | unsigned long area, offset = address - vma->vm_start; | 360 | unsigned long area, offset = address - vma->vm_start; |
361 | int ret = 0; | ||
361 | 362 | ||
362 | spu_context_nospu_trace(spufs_ps_nopfn__enter, ctx); | 363 | spu_context_nospu_trace(spufs_ps_nopfn__enter, ctx); |
363 | 364 | ||
@@ -379,7 +380,7 @@ static unsigned long spufs_ps_nopfn(struct vm_area_struct *vma, | |||
379 | if (ctx->state == SPU_STATE_SAVED) { | 380 | if (ctx->state == SPU_STATE_SAVED) { |
380 | up_read(¤t->mm->mmap_sem); | 381 | up_read(¤t->mm->mmap_sem); |
381 | spu_context_nospu_trace(spufs_ps_nopfn__sleep, ctx); | 382 | spu_context_nospu_trace(spufs_ps_nopfn__sleep, ctx); |
382 | spufs_wait(ctx->run_wq, ctx->state == SPU_STATE_RUNNABLE); | 383 | ret = spufs_wait(ctx->run_wq, ctx->state == SPU_STATE_RUNNABLE); |
383 | spu_context_trace(spufs_ps_nopfn__wake, ctx, ctx->spu); | 384 | spu_context_trace(spufs_ps_nopfn__wake, ctx, ctx->spu); |
384 | down_read(¤t->mm->mmap_sem); | 385 | down_read(¤t->mm->mmap_sem); |
385 | } else { | 386 | } else { |
@@ -388,7 +389,8 @@ static unsigned long spufs_ps_nopfn(struct vm_area_struct *vma, | |||
388 | spu_context_trace(spufs_ps_nopfn__insert, ctx, ctx->spu); | 389 | spu_context_trace(spufs_ps_nopfn__insert, ctx, ctx->spu); |
389 | } | 390 | } |
390 | 391 | ||
391 | spu_release(ctx); | 392 | if (!ret) |
393 | spu_release(ctx); | ||
392 | return NOPFN_REFAULT; | 394 | return NOPFN_REFAULT; |
393 | } | 395 | } |
394 | 396 | ||
@@ -460,7 +462,7 @@ static int spufs_cntl_open(struct inode *inode, struct file *file) | |||
460 | if (!i->i_openers++) | 462 | if (!i->i_openers++) |
461 | ctx->cntl = inode->i_mapping; | 463 | ctx->cntl = inode->i_mapping; |
462 | mutex_unlock(&ctx->mapping_lock); | 464 | mutex_unlock(&ctx->mapping_lock); |
463 | return spufs_attr_open(inode, file, spufs_cntl_get, | 465 | return simple_attr_open(inode, file, spufs_cntl_get, |
464 | spufs_cntl_set, "0x%08lx"); | 466 | spufs_cntl_set, "0x%08lx"); |
465 | } | 467 | } |
466 | 468 | ||
@@ -470,7 +472,7 @@ spufs_cntl_release(struct inode *inode, struct file *file) | |||
470 | struct spufs_inode_info *i = SPUFS_I(inode); | 472 | struct spufs_inode_info *i = SPUFS_I(inode); |
471 | struct spu_context *ctx = i->i_ctx; | 473 | struct spu_context *ctx = i->i_ctx; |
472 | 474 | ||
473 | spufs_attr_release(inode, file); | 475 | simple_attr_release(inode, file); |
474 | 476 | ||
475 | mutex_lock(&ctx->mapping_lock); | 477 | mutex_lock(&ctx->mapping_lock); |
476 | if (!--i->i_openers) | 478 | if (!--i->i_openers) |
@@ -482,8 +484,8 @@ spufs_cntl_release(struct inode *inode, struct file *file) | |||
482 | static const struct file_operations spufs_cntl_fops = { | 484 | static const struct file_operations spufs_cntl_fops = { |
483 | .open = spufs_cntl_open, | 485 | .open = spufs_cntl_open, |
484 | .release = spufs_cntl_release, | 486 | .release = spufs_cntl_release, |
485 | .read = spufs_attr_read, | 487 | .read = simple_attr_read, |
486 | .write = spufs_attr_write, | 488 | .write = simple_attr_write, |
487 | .mmap = spufs_cntl_mmap, | 489 | .mmap = spufs_cntl_mmap, |
488 | }; | 490 | }; |
489 | 491 | ||
@@ -755,23 +757,25 @@ static ssize_t spufs_ibox_read(struct file *file, char __user *buf, | |||
755 | 757 | ||
756 | count = spu_acquire(ctx); | 758 | count = spu_acquire(ctx); |
757 | if (count) | 759 | if (count) |
758 | return count; | 760 | goto out; |
759 | 761 | ||
760 | /* wait only for the first element */ | 762 | /* wait only for the first element */ |
761 | count = 0; | 763 | count = 0; |
762 | if (file->f_flags & O_NONBLOCK) { | 764 | if (file->f_flags & O_NONBLOCK) { |
763 | if (!spu_ibox_read(ctx, &ibox_data)) | 765 | if (!spu_ibox_read(ctx, &ibox_data)) { |
764 | count = -EAGAIN; | 766 | count = -EAGAIN; |
767 | goto out_unlock; | ||
768 | } | ||
765 | } else { | 769 | } else { |
766 | count = spufs_wait(ctx->ibox_wq, spu_ibox_read(ctx, &ibox_data)); | 770 | count = spufs_wait(ctx->ibox_wq, spu_ibox_read(ctx, &ibox_data)); |
771 | if (count) | ||
772 | goto out; | ||
767 | } | 773 | } |
768 | if (count) | ||
769 | goto out; | ||
770 | 774 | ||
771 | /* if we can't write at all, return -EFAULT */ | 775 | /* if we can't write at all, return -EFAULT */ |
772 | count = __put_user(ibox_data, udata); | 776 | count = __put_user(ibox_data, udata); |
773 | if (count) | 777 | if (count) |
774 | goto out; | 778 | goto out_unlock; |
775 | 779 | ||
776 | for (count = 4, udata++; (count + 4) <= len; count += 4, udata++) { | 780 | for (count = 4, udata++; (count + 4) <= len; count += 4, udata++) { |
777 | int ret; | 781 | int ret; |
@@ -788,9 +792,9 @@ static ssize_t spufs_ibox_read(struct file *file, char __user *buf, | |||
788 | break; | 792 | break; |
789 | } | 793 | } |
790 | 794 | ||
791 | out: | 795 | out_unlock: |
792 | spu_release(ctx); | 796 | spu_release(ctx); |
793 | 797 | out: | |
794 | return count; | 798 | return count; |
795 | } | 799 | } |
796 | 800 | ||
@@ -905,7 +909,7 @@ static ssize_t spufs_wbox_write(struct file *file, const char __user *buf, | |||
905 | 909 | ||
906 | count = spu_acquire(ctx); | 910 | count = spu_acquire(ctx); |
907 | if (count) | 911 | if (count) |
908 | return count; | 912 | goto out; |
909 | 913 | ||
910 | /* | 914 | /* |
911 | * make sure we can at least write one element, by waiting | 915 | * make sure we can at least write one element, by waiting |
@@ -913,14 +917,16 @@ static ssize_t spufs_wbox_write(struct file *file, const char __user *buf, | |||
913 | */ | 917 | */ |
914 | count = 0; | 918 | count = 0; |
915 | if (file->f_flags & O_NONBLOCK) { | 919 | if (file->f_flags & O_NONBLOCK) { |
916 | if (!spu_wbox_write(ctx, wbox_data)) | 920 | if (!spu_wbox_write(ctx, wbox_data)) { |
917 | count = -EAGAIN; | 921 | count = -EAGAIN; |
922 | goto out_unlock; | ||
923 | } | ||
918 | } else { | 924 | } else { |
919 | count = spufs_wait(ctx->wbox_wq, spu_wbox_write(ctx, wbox_data)); | 925 | count = spufs_wait(ctx->wbox_wq, spu_wbox_write(ctx, wbox_data)); |
926 | if (count) | ||
927 | goto out; | ||
920 | } | 928 | } |
921 | 929 | ||
922 | if (count) | ||
923 | goto out; | ||
924 | 930 | ||
925 | /* write as much as possible */ | 931 | /* write as much as possible */ |
926 | for (count = 4, udata++; (count + 4) <= len; count += 4, udata++) { | 932 | for (count = 4, udata++; (count + 4) <= len; count += 4, udata++) { |
@@ -934,8 +940,9 @@ static ssize_t spufs_wbox_write(struct file *file, const char __user *buf, | |||
934 | break; | 940 | break; |
935 | } | 941 | } |
936 | 942 | ||
937 | out: | 943 | out_unlock: |
938 | spu_release(ctx); | 944 | spu_release(ctx); |
945 | out: | ||
939 | return count; | 946 | return count; |
940 | } | 947 | } |
941 | 948 | ||
@@ -1598,12 +1605,11 @@ static ssize_t spufs_mfc_read(struct file *file, char __user *buffer, | |||
1598 | } else { | 1605 | } else { |
1599 | ret = spufs_wait(ctx->mfc_wq, | 1606 | ret = spufs_wait(ctx->mfc_wq, |
1600 | spufs_read_mfc_tagstatus(ctx, &status)); | 1607 | spufs_read_mfc_tagstatus(ctx, &status)); |
1608 | if (ret) | ||
1609 | goto out; | ||
1601 | } | 1610 | } |
1602 | spu_release(ctx); | 1611 | spu_release(ctx); |
1603 | 1612 | ||
1604 | if (ret) | ||
1605 | goto out; | ||
1606 | |||
1607 | ret = 4; | 1613 | ret = 4; |
1608 | if (copy_to_user(buffer, &status, 4)) | 1614 | if (copy_to_user(buffer, &status, 4)) |
1609 | ret = -EFAULT; | 1615 | ret = -EFAULT; |
@@ -1732,6 +1738,8 @@ static ssize_t spufs_mfc_write(struct file *file, const char __user *buffer, | |||
1732 | int status; | 1738 | int status; |
1733 | ret = spufs_wait(ctx->mfc_wq, | 1739 | ret = spufs_wait(ctx->mfc_wq, |
1734 | spu_send_mfc_command(ctx, cmd, &status)); | 1740 | spu_send_mfc_command(ctx, cmd, &status)); |
1741 | if (ret) | ||
1742 | goto out; | ||
1735 | if (status) | 1743 | if (status) |
1736 | ret = status; | 1744 | ret = status; |
1737 | } | 1745 | } |
@@ -1785,7 +1793,7 @@ static int spufs_mfc_flush(struct file *file, fl_owner_t id) | |||
1785 | 1793 | ||
1786 | ret = spu_acquire(ctx); | 1794 | ret = spu_acquire(ctx); |
1787 | if (ret) | 1795 | if (ret) |
1788 | return ret; | 1796 | goto out; |
1789 | #if 0 | 1797 | #if 0 |
1790 | /* this currently hangs */ | 1798 | /* this currently hangs */ |
1791 | ret = spufs_wait(ctx->mfc_wq, | 1799 | ret = spufs_wait(ctx->mfc_wq, |
@@ -1794,12 +1802,13 @@ static int spufs_mfc_flush(struct file *file, fl_owner_t id) | |||
1794 | goto out; | 1802 | goto out; |
1795 | ret = spufs_wait(ctx->mfc_wq, | 1803 | ret = spufs_wait(ctx->mfc_wq, |
1796 | ctx->ops->read_mfc_tagstatus(ctx) == ctx->tagwait); | 1804 | ctx->ops->read_mfc_tagstatus(ctx) == ctx->tagwait); |
1797 | out: | 1805 | if (ret) |
1806 | goto out; | ||
1798 | #else | 1807 | #else |
1799 | ret = 0; | 1808 | ret = 0; |
1800 | #endif | 1809 | #endif |
1801 | spu_release(ctx); | 1810 | spu_release(ctx); |
1802 | 1811 | out: | |
1803 | return ret; | 1812 | return ret; |
1804 | } | 1813 | } |
1805 | 1814 | ||
diff --git a/arch/powerpc/platforms/cell/spufs/inode.c b/arch/powerpc/platforms/cell/spufs/inode.c index 90784c029f25..e6e6559c55ed 100644 --- a/arch/powerpc/platforms/cell/spufs/inode.c +++ b/arch/powerpc/platforms/cell/spufs/inode.c | |||
@@ -755,8 +755,11 @@ spufs_fill_super(struct super_block *sb, void *data, int silent) | |||
755 | .statfs = simple_statfs, | 755 | .statfs = simple_statfs, |
756 | .delete_inode = spufs_delete_inode, | 756 | .delete_inode = spufs_delete_inode, |
757 | .drop_inode = generic_delete_inode, | 757 | .drop_inode = generic_delete_inode, |
758 | .show_options = generic_show_options, | ||
758 | }; | 759 | }; |
759 | 760 | ||
761 | save_mount_options(sb, data); | ||
762 | |||
760 | sb->s_maxbytes = MAX_LFS_FILESIZE; | 763 | sb->s_maxbytes = MAX_LFS_FILESIZE; |
761 | sb->s_blocksize = PAGE_CACHE_SIZE; | 764 | sb->s_blocksize = PAGE_CACHE_SIZE; |
762 | sb->s_blocksize_bits = PAGE_CACHE_SHIFT; | 765 | sb->s_blocksize_bits = PAGE_CACHE_SHIFT; |
diff --git a/arch/powerpc/platforms/cell/spufs/run.c b/arch/powerpc/platforms/cell/spufs/run.c index b4814c740d8a..fca22e18069a 100644 --- a/arch/powerpc/platforms/cell/spufs/run.c +++ b/arch/powerpc/platforms/cell/spufs/run.c | |||
@@ -53,7 +53,7 @@ int spu_stopped(struct spu_context *ctx, u32 *stat) | |||
53 | 53 | ||
54 | stopped = SPU_STATUS_INVALID_INSTR | SPU_STATUS_SINGLE_STEP | | 54 | stopped = SPU_STATUS_INVALID_INSTR | SPU_STATUS_SINGLE_STEP | |
55 | SPU_STATUS_STOPPED_BY_HALT | SPU_STATUS_STOPPED_BY_STOP; | 55 | SPU_STATUS_STOPPED_BY_HALT | SPU_STATUS_STOPPED_BY_STOP; |
56 | if (*stat & stopped) | 56 | if (!(*stat & SPU_STATUS_RUNNING) && (*stat & stopped)) |
57 | return 1; | 57 | return 1; |
58 | 58 | ||
59 | dsisr = ctx->csa.dsisr; | 59 | dsisr = ctx->csa.dsisr; |
@@ -354,8 +354,15 @@ long spufs_run_spu(struct spu_context *ctx, u32 *npc, u32 *event) | |||
354 | 354 | ||
355 | do { | 355 | do { |
356 | ret = spufs_wait(ctx->stop_wq, spu_stopped(ctx, &status)); | 356 | ret = spufs_wait(ctx->stop_wq, spu_stopped(ctx, &status)); |
357 | if (unlikely(ret)) | 357 | if (unlikely(ret)) { |
358 | /* | ||
359 | * This is nasty: we need the state_mutex for all the | ||
360 | * bookkeeping even if the syscall was interrupted by | ||
361 | * a signal. ewww. | ||
362 | */ | ||
363 | mutex_lock(&ctx->state_mutex); | ||
358 | break; | 364 | break; |
365 | } | ||
359 | spu = ctx->spu; | 366 | spu = ctx->spu; |
360 | if (unlikely(test_and_clear_bit(SPU_SCHED_NOTIFY_ACTIVE, | 367 | if (unlikely(test_and_clear_bit(SPU_SCHED_NOTIFY_ACTIVE, |
361 | &ctx->sched_flags))) { | 368 | &ctx->sched_flags))) { |
@@ -388,16 +395,14 @@ long spufs_run_spu(struct spu_context *ctx, u32 *npc, u32 *event) | |||
388 | SPU_STATUS_STOPPED_BY_HALT | | 395 | SPU_STATUS_STOPPED_BY_HALT | |
389 | SPU_STATUS_SINGLE_STEP))); | 396 | SPU_STATUS_SINGLE_STEP))); |
390 | 397 | ||
391 | if ((status & SPU_STATUS_STOPPED_BY_STOP) && | ||
392 | (((status >> SPU_STOP_STATUS_SHIFT) & 0x3f00) == 0x2100) && | ||
393 | (ctx->state == SPU_STATE_RUNNABLE)) | ||
394 | ctx->stats.libassist++; | ||
395 | |||
396 | |||
397 | spu_disable_spu(ctx); | 398 | spu_disable_spu(ctx); |
398 | ret = spu_run_fini(ctx, npc, &status); | 399 | ret = spu_run_fini(ctx, npc, &status); |
399 | spu_yield(ctx); | 400 | spu_yield(ctx); |
400 | 401 | ||
402 | if ((status & SPU_STATUS_STOPPED_BY_STOP) && | ||
403 | (((status >> SPU_STOP_STATUS_SHIFT) & 0x3f00) == 0x2100)) | ||
404 | ctx->stats.libassist++; | ||
405 | |||
401 | if ((ret == 0) || | 406 | if ((ret == 0) || |
402 | ((ret == -ERESTARTSYS) && | 407 | ((ret == -ERESTARTSYS) && |
403 | ((status & SPU_STATUS_STOPPED_BY_HALT) || | 408 | ((status & SPU_STATUS_STOPPED_BY_HALT) || |
diff --git a/arch/powerpc/platforms/cell/spufs/spufs.h b/arch/powerpc/platforms/cell/spufs/spufs.h index 795a1b52538b..2c2fe3c07d72 100644 --- a/arch/powerpc/platforms/cell/spufs/spufs.h +++ b/arch/powerpc/platforms/cell/spufs/spufs.h | |||
@@ -268,6 +268,9 @@ extern char *isolated_loader; | |||
268 | * Same as wait_event_interruptible(), except that here | 268 | * Same as wait_event_interruptible(), except that here |
269 | * we need to call spu_release(ctx) before sleeping, and | 269 | * we need to call spu_release(ctx) before sleeping, and |
270 | * then spu_acquire(ctx) when awoken. | 270 | * then spu_acquire(ctx) when awoken. |
271 | * | ||
272 | * Returns with state_mutex re-acquired when successfull or | ||
273 | * with -ERESTARTSYS and the state_mutex dropped when interrupted. | ||
271 | */ | 274 | */ |
272 | 275 | ||
273 | #define spufs_wait(wq, condition) \ | 276 | #define spufs_wait(wq, condition) \ |
@@ -278,11 +281,11 @@ extern char *isolated_loader; | |||
278 | prepare_to_wait(&(wq), &__wait, TASK_INTERRUPTIBLE); \ | 281 | prepare_to_wait(&(wq), &__wait, TASK_INTERRUPTIBLE); \ |
279 | if (condition) \ | 282 | if (condition) \ |
280 | break; \ | 283 | break; \ |
284 | spu_release(ctx); \ | ||
281 | if (signal_pending(current)) { \ | 285 | if (signal_pending(current)) { \ |
282 | __ret = -ERESTARTSYS; \ | 286 | __ret = -ERESTARTSYS; \ |
283 | break; \ | 287 | break; \ |
284 | } \ | 288 | } \ |
285 | spu_release(ctx); \ | ||
286 | schedule(); \ | 289 | schedule(); \ |
287 | __ret = spu_acquire(ctx); \ | 290 | __ret = spu_acquire(ctx); \ |
288 | if (__ret) \ | 291 | if (__ret) \ |
diff --git a/arch/powerpc/platforms/powermac/feature.c b/arch/powerpc/platforms/powermac/feature.c index ba931be2175c..5169ecc37123 100644 --- a/arch/powerpc/platforms/powermac/feature.c +++ b/arch/powerpc/platforms/powermac/feature.c | |||
@@ -2565,6 +2565,8 @@ static void __init probe_uninorth(void) | |||
2565 | 2565 | ||
2566 | /* Locate core99 Uni-N */ | 2566 | /* Locate core99 Uni-N */ |
2567 | uninorth_node = of_find_node_by_name(NULL, "uni-n"); | 2567 | uninorth_node = of_find_node_by_name(NULL, "uni-n"); |
2568 | uninorth_maj = 1; | ||
2569 | |||
2568 | /* Locate G5 u3 */ | 2570 | /* Locate G5 u3 */ |
2569 | if (uninorth_node == NULL) { | 2571 | if (uninorth_node == NULL) { |
2570 | uninorth_node = of_find_node_by_name(NULL, "u3"); | 2572 | uninorth_node = of_find_node_by_name(NULL, "u3"); |
@@ -2575,8 +2577,10 @@ static void __init probe_uninorth(void) | |||
2575 | uninorth_node = of_find_node_by_name(NULL, "u4"); | 2577 | uninorth_node = of_find_node_by_name(NULL, "u4"); |
2576 | uninorth_maj = 4; | 2578 | uninorth_maj = 4; |
2577 | } | 2579 | } |
2578 | if (uninorth_node == NULL) | 2580 | if (uninorth_node == NULL) { |
2581 | uninorth_maj = 0; | ||
2579 | return; | 2582 | return; |
2583 | } | ||
2580 | 2584 | ||
2581 | addrp = of_get_property(uninorth_node, "reg", NULL); | 2585 | addrp = of_get_property(uninorth_node, "reg", NULL); |
2582 | if (addrp == NULL) | 2586 | if (addrp == NULL) |
@@ -3029,3 +3033,8 @@ void pmac_resume_agp_for_card(struct pci_dev *dev) | |||
3029 | pmac_agp_resume(pmac_agp_bridge); | 3033 | pmac_agp_resume(pmac_agp_bridge); |
3030 | } | 3034 | } |
3031 | EXPORT_SYMBOL(pmac_resume_agp_for_card); | 3035 | EXPORT_SYMBOL(pmac_resume_agp_for_card); |
3036 | |||
3037 | int pmac_get_uninorth_variant(void) | ||
3038 | { | ||
3039 | return uninorth_maj; | ||
3040 | } | ||