diff options
author | Benjamin Herrenschmidt <benh@kernel.crashing.org> | 2007-02-12 19:46:08 -0500 |
---|---|---|
committer | Paul Mackerras <paulus@samba.org> | 2007-02-12 23:35:54 -0500 |
commit | 17e0e27020d028a790d97699aff85a43af5be472 (patch) | |
tree | f3dd43243be6e840dc2b0386e91c4146a4f51620 /arch | |
parent | 44430e0d3916ab6aaf0451fdb811f4f1803b741e (diff) |
[POWERPC] spufs: Fix bitrot of the SPU mmap facility
It looks like we've had some serious bitrot there mostly due to tracking
of address_space's of mmap'ed files getting out of sync with the actual
mmap code. The mfc, mss and psmap were not tracked properly and thus
not invalidated on context switches (oops !)
I also removed the various file->f_mapping = inode->i_mapping;
assignments that were done in the other open() routines since that
is already done for us by __dentry_open.
One improvement we might want to do later is to assign the various
ctx-> fields at mmap time instead of file open/close time so that we
don't call unmap_mapping_range() on thing that have not been mmap'ed
Finally, I added some smp_wmb's after assigning the ctx-> fields to make
sure they are visible to other CPUs. I don't think this is really
necessary as I suspect locking in the fs layer will make that happen
anyway but better safe than sorry.
Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
Signed-off-by: Paul Mackerras <paulus@samba.org>
Diffstat (limited to 'arch')
-rw-r--r-- | arch/powerpc/platforms/cell/spufs/context.c | 12 | ||||
-rw-r--r-- | arch/powerpc/platforms/cell/spufs/file.c | 16 | ||||
-rw-r--r-- | arch/powerpc/platforms/cell/spufs/spufs.h | 2 |
3 files changed, 22 insertions, 8 deletions
diff --git a/arch/powerpc/platforms/cell/spufs/context.c b/arch/powerpc/platforms/cell/spufs/context.c index 0870009f56db..28c718ca3b51 100644 --- a/arch/powerpc/platforms/cell/spufs/context.c +++ b/arch/powerpc/platforms/cell/spufs/context.c | |||
@@ -111,13 +111,17 @@ void spu_unmap_mappings(struct spu_context *ctx) | |||
111 | if (ctx->local_store) | 111 | if (ctx->local_store) |
112 | unmap_mapping_range(ctx->local_store, 0, LS_SIZE, 1); | 112 | unmap_mapping_range(ctx->local_store, 0, LS_SIZE, 1); |
113 | if (ctx->mfc) | 113 | if (ctx->mfc) |
114 | unmap_mapping_range(ctx->mfc, 0, 0x4000, 1); | 114 | unmap_mapping_range(ctx->mfc, 0, 0x1000, 1); |
115 | if (ctx->cntl) | 115 | if (ctx->cntl) |
116 | unmap_mapping_range(ctx->cntl, 0, 0x4000, 1); | 116 | unmap_mapping_range(ctx->cntl, 0, 0x1000, 1); |
117 | if (ctx->signal1) | 117 | if (ctx->signal1) |
118 | unmap_mapping_range(ctx->signal1, 0, 0x4000, 1); | 118 | unmap_mapping_range(ctx->signal1, 0, PAGE_SIZE, 1); |
119 | if (ctx->signal2) | 119 | if (ctx->signal2) |
120 | unmap_mapping_range(ctx->signal2, 0, 0x4000, 1); | 120 | unmap_mapping_range(ctx->signal2, 0, PAGE_SIZE, 1); |
121 | if (ctx->mss) | ||
122 | unmap_mapping_range(ctx->mss, 0, 0x1000, 1); | ||
123 | if (ctx->psmap) | ||
124 | unmap_mapping_range(ctx->psmap, 0, 0x20000, 1); | ||
121 | } | 125 | } |
122 | 126 | ||
123 | int spu_acquire_exclusive(struct spu_context *ctx) | 127 | int spu_acquire_exclusive(struct spu_context *ctx) |
diff --git a/arch/powerpc/platforms/cell/spufs/file.c b/arch/powerpc/platforms/cell/spufs/file.c index 7fb9a6dc4f18..a528020baa18 100644 --- a/arch/powerpc/platforms/cell/spufs/file.c +++ b/arch/powerpc/platforms/cell/spufs/file.c | |||
@@ -45,8 +45,8 @@ spufs_mem_open(struct inode *inode, struct file *file) | |||
45 | struct spufs_inode_info *i = SPUFS_I(inode); | 45 | struct spufs_inode_info *i = SPUFS_I(inode); |
46 | struct spu_context *ctx = i->i_ctx; | 46 | struct spu_context *ctx = i->i_ctx; |
47 | file->private_data = ctx; | 47 | file->private_data = ctx; |
48 | file->f_mapping = inode->i_mapping; | ||
49 | ctx->local_store = inode->i_mapping; | 48 | ctx->local_store = inode->i_mapping; |
49 | smp_wmb(); | ||
50 | return 0; | 50 | return 0; |
51 | } | 51 | } |
52 | 52 | ||
@@ -232,8 +232,8 @@ static int spufs_cntl_open(struct inode *inode, struct file *file) | |||
232 | struct spu_context *ctx = i->i_ctx; | 232 | struct spu_context *ctx = i->i_ctx; |
233 | 233 | ||
234 | file->private_data = ctx; | 234 | file->private_data = ctx; |
235 | file->f_mapping = inode->i_mapping; | ||
236 | ctx->cntl = inode->i_mapping; | 235 | ctx->cntl = inode->i_mapping; |
236 | smp_wmb(); | ||
237 | return simple_attr_open(inode, file, spufs_cntl_get, | 237 | return simple_attr_open(inode, file, spufs_cntl_get, |
238 | spufs_cntl_set, "0x%08lx"); | 238 | spufs_cntl_set, "0x%08lx"); |
239 | } | 239 | } |
@@ -717,8 +717,8 @@ static int spufs_signal1_open(struct inode *inode, struct file *file) | |||
717 | struct spufs_inode_info *i = SPUFS_I(inode); | 717 | struct spufs_inode_info *i = SPUFS_I(inode); |
718 | struct spu_context *ctx = i->i_ctx; | 718 | struct spu_context *ctx = i->i_ctx; |
719 | file->private_data = ctx; | 719 | file->private_data = ctx; |
720 | file->f_mapping = inode->i_mapping; | ||
721 | ctx->signal1 = inode->i_mapping; | 720 | ctx->signal1 = inode->i_mapping; |
721 | smp_wmb(); | ||
722 | return nonseekable_open(inode, file); | 722 | return nonseekable_open(inode, file); |
723 | } | 723 | } |
724 | 724 | ||
@@ -824,8 +824,8 @@ static int spufs_signal2_open(struct inode *inode, struct file *file) | |||
824 | struct spufs_inode_info *i = SPUFS_I(inode); | 824 | struct spufs_inode_info *i = SPUFS_I(inode); |
825 | struct spu_context *ctx = i->i_ctx; | 825 | struct spu_context *ctx = i->i_ctx; |
826 | file->private_data = ctx; | 826 | file->private_data = ctx; |
827 | file->f_mapping = inode->i_mapping; | ||
828 | ctx->signal2 = inode->i_mapping; | 827 | ctx->signal2 = inode->i_mapping; |
828 | smp_wmb(); | ||
829 | return nonseekable_open(inode, file); | 829 | return nonseekable_open(inode, file); |
830 | } | 830 | } |
831 | 831 | ||
@@ -1021,8 +1021,11 @@ static int spufs_mss_mmap(struct file *file, struct vm_area_struct *vma) | |||
1021 | static int spufs_mss_open(struct inode *inode, struct file *file) | 1021 | static int spufs_mss_open(struct inode *inode, struct file *file) |
1022 | { | 1022 | { |
1023 | struct spufs_inode_info *i = SPUFS_I(inode); | 1023 | struct spufs_inode_info *i = SPUFS_I(inode); |
1024 | struct spu_context *ctx = i->i_ctx; | ||
1024 | 1025 | ||
1025 | file->private_data = i->i_ctx; | 1026 | file->private_data = i->i_ctx; |
1027 | ctx->mss = inode->i_mapping; | ||
1028 | smp_wmb(); | ||
1026 | return nonseekable_open(inode, file); | 1029 | return nonseekable_open(inode, file); |
1027 | } | 1030 | } |
1028 | 1031 | ||
@@ -1060,8 +1063,11 @@ static int spufs_psmap_mmap(struct file *file, struct vm_area_struct *vma) | |||
1060 | static int spufs_psmap_open(struct inode *inode, struct file *file) | 1063 | static int spufs_psmap_open(struct inode *inode, struct file *file) |
1061 | { | 1064 | { |
1062 | struct spufs_inode_info *i = SPUFS_I(inode); | 1065 | struct spufs_inode_info *i = SPUFS_I(inode); |
1066 | struct spu_context *ctx = i->i_ctx; | ||
1063 | 1067 | ||
1064 | file->private_data = i->i_ctx; | 1068 | file->private_data = i->i_ctx; |
1069 | ctx->psmap = inode->i_mapping; | ||
1070 | smp_wmb(); | ||
1065 | return nonseekable_open(inode, file); | 1071 | return nonseekable_open(inode, file); |
1066 | } | 1072 | } |
1067 | 1073 | ||
@@ -1114,6 +1120,8 @@ static int spufs_mfc_open(struct inode *inode, struct file *file) | |||
1114 | return -EBUSY; | 1120 | return -EBUSY; |
1115 | 1121 | ||
1116 | file->private_data = ctx; | 1122 | file->private_data = ctx; |
1123 | ctx->mfc = inode->i_mapping; | ||
1124 | smp_wmb(); | ||
1117 | return nonseekable_open(inode, file); | 1125 | return nonseekable_open(inode, file); |
1118 | } | 1126 | } |
1119 | 1127 | ||
diff --git a/arch/powerpc/platforms/cell/spufs/spufs.h b/arch/powerpc/platforms/cell/spufs/spufs.h index 56864469215e..0941c56df9b5 100644 --- a/arch/powerpc/platforms/cell/spufs/spufs.h +++ b/arch/powerpc/platforms/cell/spufs/spufs.h | |||
@@ -51,6 +51,8 @@ struct spu_context { | |||
51 | struct address_space *cntl; /* 'control' area mappings. */ | 51 | struct address_space *cntl; /* 'control' area mappings. */ |
52 | struct address_space *signal1; /* 'signal1' area mappings. */ | 52 | struct address_space *signal1; /* 'signal1' area mappings. */ |
53 | struct address_space *signal2; /* 'signal2' area mappings. */ | 53 | struct address_space *signal2; /* 'signal2' area mappings. */ |
54 | struct address_space *mss; /* 'mss' area mappings. */ | ||
55 | struct address_space *psmap; /* 'psmap' area mappings. */ | ||
54 | u64 object_id; /* user space pointer for oprofile */ | 56 | u64 object_id; /* user space pointer for oprofile */ |
55 | 57 | ||
56 | enum { SPU_STATE_RUNNABLE, SPU_STATE_SAVED } state; | 58 | enum { SPU_STATE_RUNNABLE, SPU_STATE_SAVED } state; |