aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDwayne Grant McConnell <decimal@us.ibm.com>2006-11-20 12:45:01 -0500
committerPaul Mackerras <paulus@samba.org>2006-12-04 04:39:50 -0500
commit17f88cebc2c3aff9d90f0d49f6e0628835eddc32 (patch)
treed22b5b04d4bd4d3cc2ab87dcee28918c2abbd2fa
parent69a2f00ce5d3a19a70b36f08eaf9049677277710 (diff)
[POWERPC] spufs: Read from signal files only if data is there
We need to check the channel count of the signal notification registers before reading them, because it can be undefined when the count is zero. In order to read count and data atomically, we read from the saved context. This patch uses spu_acquire_saved() to force a context save before a /signal1 or /signal2 read. Because of this it is no longer necessary to have backing_ops and hw_ops versions of this function so they have been removed. Regular applications should not rely on reading this register to be fast, as it's conceptually a write-only file from the PPE perspective. Signed-off-by: Dwayne Grant McConnell <decimal@us.ibm.com> Signed-off-by: Arnd Bergmann <arnd.bergmann@de.ibm.com> Signed-off-by: Paul Mackerras <paulus@samba.org>
-rw-r--r--arch/powerpc/platforms/cell/spufs/file.c30
-rw-r--r--arch/powerpc/platforms/cell/spufs/hw_ops.c12
2 files changed, 22 insertions, 20 deletions
diff --git a/arch/powerpc/platforms/cell/spufs/file.c b/arch/powerpc/platforms/cell/spufs/file.c
index 2a2dd6441010..c0cf9ee4d45f 100644
--- a/arch/powerpc/platforms/cell/spufs/file.c
+++ b/arch/powerpc/platforms/cell/spufs/file.c
@@ -723,19 +723,27 @@ static ssize_t spufs_signal1_read(struct file *file, char __user *buf,
723 size_t len, loff_t *pos) 723 size_t len, loff_t *pos)
724{ 724{
725 struct spu_context *ctx = file->private_data; 725 struct spu_context *ctx = file->private_data;
726 int ret = 0;
726 u32 data; 727 u32 data;
727 728
728 if (len < 4) 729 if (len < 4)
729 return -EINVAL; 730 return -EINVAL;
730 731
731 spu_acquire(ctx); 732 spu_acquire_saved(ctx);
732 data = ctx->ops->signal1_read(ctx); 733 if (ctx->csa.spu_chnlcnt_RW[3]) {
734 data = ctx->csa.spu_chnldata_RW[3];
735 ret = 4;
736 }
733 spu_release(ctx); 737 spu_release(ctx);
734 738
739 if (!ret)
740 goto out;
741
735 if (copy_to_user(buf, &data, 4)) 742 if (copy_to_user(buf, &data, 4))
736 return -EFAULT; 743 return -EFAULT;
737 744
738 return 4; 745out:
746 return ret;
739} 747}
740 748
741static ssize_t spufs_signal1_write(struct file *file, const char __user *buf, 749static ssize_t spufs_signal1_write(struct file *file, const char __user *buf,
@@ -811,21 +819,27 @@ static int spufs_signal2_open(struct inode *inode, struct file *file)
811static ssize_t spufs_signal2_read(struct file *file, char __user *buf, 819static ssize_t spufs_signal2_read(struct file *file, char __user *buf,
812 size_t len, loff_t *pos) 820 size_t len, loff_t *pos)
813{ 821{
814 struct spu_context *ctx; 822 struct spu_context *ctx = file->private_data;
823 int ret = 0;
815 u32 data; 824 u32 data;
816 825
817 ctx = file->private_data;
818
819 if (len < 4) 826 if (len < 4)
820 return -EINVAL; 827 return -EINVAL;
821 828
822 spu_acquire(ctx); 829 spu_acquire_saved(ctx);
823 data = ctx->ops->signal2_read(ctx); 830 if (ctx->csa.spu_chnlcnt_RW[4]) {
831 data = ctx->csa.spu_chnldata_RW[4];
832 ret = 4;
833 }
824 spu_release(ctx); 834 spu_release(ctx);
825 835
836 if (!ret)
837 goto out;
838
826 if (copy_to_user(buf, &data, 4)) 839 if (copy_to_user(buf, &data, 4))
827 return -EFAULT; 840 return -EFAULT;
828 841
842out:
829 return 4; 843 return 4;
830} 844}
831 845
diff --git a/arch/powerpc/platforms/cell/spufs/hw_ops.c b/arch/powerpc/platforms/cell/spufs/hw_ops.c
index 59c87f12da5a..79c304e815a1 100644
--- a/arch/powerpc/platforms/cell/spufs/hw_ops.c
+++ b/arch/powerpc/platforms/cell/spufs/hw_ops.c
@@ -135,21 +135,11 @@ static int spu_hw_wbox_write(struct spu_context *ctx, u32 data)
135 return ret; 135 return ret;
136} 136}
137 137
138static u32 spu_hw_signal1_read(struct spu_context *ctx)
139{
140 return in_be32(&ctx->spu->problem->signal_notify1);
141}
142
143static void spu_hw_signal1_write(struct spu_context *ctx, u32 data) 138static void spu_hw_signal1_write(struct spu_context *ctx, u32 data)
144{ 139{
145 out_be32(&ctx->spu->problem->signal_notify1, data); 140 out_be32(&ctx->spu->problem->signal_notify1, data);
146} 141}
147 142
148static u32 spu_hw_signal2_read(struct spu_context *ctx)
149{
150 return in_be32(&ctx->spu->problem->signal_notify2);
151}
152
153static void spu_hw_signal2_write(struct spu_context *ctx, u32 data) 143static void spu_hw_signal2_write(struct spu_context *ctx, u32 data)
154{ 144{
155 out_be32(&ctx->spu->problem->signal_notify2, data); 145 out_be32(&ctx->spu->problem->signal_notify2, data);
@@ -294,9 +284,7 @@ struct spu_context_ops spu_hw_ops = {
294 .mbox_stat_poll = spu_hw_mbox_stat_poll, 284 .mbox_stat_poll = spu_hw_mbox_stat_poll,
295 .ibox_read = spu_hw_ibox_read, 285 .ibox_read = spu_hw_ibox_read,
296 .wbox_write = spu_hw_wbox_write, 286 .wbox_write = spu_hw_wbox_write,
297 .signal1_read = spu_hw_signal1_read,
298 .signal1_write = spu_hw_signal1_write, 287 .signal1_write = spu_hw_signal1_write,
299 .signal2_read = spu_hw_signal2_read,
300 .signal2_write = spu_hw_signal2_write, 288 .signal2_write = spu_hw_signal2_write,
301 .signal1_type_set = spu_hw_signal1_type_set, 289 .signal1_type_set = spu_hw_signal1_type_set,
302 .signal1_type_get = spu_hw_signal1_type_get, 290 .signal1_type_get = spu_hw_signal1_type_get,