aboutsummaryrefslogtreecommitdiffstats
path: root/arch/powerpc/platforms/cell/spufs
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@woody.linux-foundation.org>2008-02-08 12:31:42 -0500
committerLinus Torvalds <torvalds@woody.linux-foundation.org>2008-02-08 12:31:42 -0500
commitdde0013782dbd09e1cc68ca03860f3a62b03cb34 (patch)
tree5be40012944c0fab834a385f2410eaa60e2b0d6e /arch/powerpc/platforms/cell/spufs
parentf3aafa6c2535d36542a6dfc8647cd2fdb5999648 (diff)
parenta99824f327c748b2753f4fa570eb1fefcd6a9c4d (diff)
Merge branch 'for-2.6.25' of git://git.kernel.org/pub/scm/linux/kernel/git/paulus/powerpc
* 'for-2.6.25' of git://git.kernel.org/pub/scm/linux/kernel/git/paulus/powerpc: [POWERPC] Add arch-specific walk_memory_remove() for 64-bit powerpc [POWERPC] Enable hotplug memory remove for 64-bit powerpc [POWERPC] Add remove_memory() for 64-bit powerpc [POWERPC] Make cell IOMMU fixed mapping printk more useful [POWERPC] Fix potential cell IOMMU bug when switching back to default DMA ops [POWERPC] Don't enable cell IOMMU fixed mapping if there are no dma-ranges [POWERPC] Fix cell IOMMU null pointer explosion on old firmwares [POWERPC] spufs: Fix timing dependent false return from spufs_run_spu [POWERPC] spufs: No need to have a runnable SPU for libassist update [POWERPC] spufs: Update SPU_Status[CISHP] in backing runcntl write [POWERPC] spufs: Fix state_mutex leaks [POWERPC] Disable G5 NAP mode during SMU commands on U3
Diffstat (limited to 'arch/powerpc/platforms/cell/spufs')
-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.c49
-rw-r--r--arch/powerpc/platforms/cell/spufs/run.c21
-rw-r--r--arch/powerpc/platforms/cell/spufs/spufs.h5
5 files changed, 56 insertions, 37 deletions
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 e393144d533d..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
@@ -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/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) \