aboutsummaryrefslogtreecommitdiffstats
path: root/arch/powerpc
diff options
context:
space:
mode:
Diffstat (limited to 'arch/powerpc')
-rw-r--r--arch/powerpc/Kconfig6
-rw-r--r--arch/powerpc/mm/mem.c33
-rw-r--r--arch/powerpc/mm/pgtable_32.c14
-rw-r--r--arch/powerpc/platforms/cell/iommu.c48
-rw-r--r--arch/powerpc/platforms/cell/spufs/backing_ops.c6
-rw-r--r--arch/powerpc/platforms/cell/spufs/fault.c12
-rw-r--r--arch/powerpc/platforms/cell/spufs/file.c57
-rw-r--r--arch/powerpc/platforms/cell/spufs/inode.c3
-rw-r--r--arch/powerpc/platforms/cell/spufs/run.c21
-rw-r--r--arch/powerpc/platforms/cell/spufs/spufs.h5
-rw-r--r--arch/powerpc/platforms/powermac/feature.c11
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
272config ARCH_ENABLE_MEMORY_HOTPLUG 272config ARCH_ENABLE_MEMORY_HOTPLUG
273 def_bool y 273 def_bool y
274 274
275config ARCH_HAS_WALK_MEMORY
276 def_bool y
277
278config ARCH_ENABLE_MEMORY_HOTREMOVE
279 def_bool y
280
275config KEXEC 281config 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
133int 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 */
144out:
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 */
158int
159walk_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
134void show_mem(void) 167void 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
110struct page *pte_alloc_one(struct mm_struct *mm, unsigned long address) 110pgtable_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
134void pte_free(struct mm_struct *mm, struct page *ptepage) 135void 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)
789static u64 cell_iommu_get_fixed_address(struct device *dev) 790static 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(&current->mm->mmap_sem); 381 up_read(&current->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(&current->mm->mmap_sem); 385 down_read(&current->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)
482static const struct file_operations spufs_cntl_fops = { 484static 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
791out: 795out_unlock:
792 spu_release(ctx); 796 spu_release(ctx);
793 797out:
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
937out: 943out_unlock:
938 spu_release(ctx); 944 spu_release(ctx);
945out:
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);
1797out: 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 1811out:
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}
3031EXPORT_SYMBOL(pmac_resume_agp_for_card); 3035EXPORT_SYMBOL(pmac_resume_agp_for_card);
3036
3037int pmac_get_uninorth_variant(void)
3038{
3039 return uninorth_maj;
3040}