diff options
author | Christoph Hellwig <hch@lst.de> | 2007-06-04 09:26:51 -0400 |
---|---|---|
committer | Paul Mackerras <paulus@samba.org> | 2007-06-06 21:44:39 -0400 |
commit | 47d3a5faa3f72186f769ed9579c630afb8433f2b (patch) | |
tree | 01e33e214b40d34ee6051d1381ba87521caa5d82 | |
parent | 89df00855beabfa700f9a9ed52f0983bdc4b021d (diff) |
[POWERPC] spufs: Synchronize pte invalidation vs ps close
Make sure the mapping_lock also protects access to the various address_space
pointers used for tearing down the ptes on a spu context switch.
Because unmap_mapping_range can sleep we need to turn mapping_lock from
a spinlock into a sleeping mutex.
Signed-off-by: Christoph Hellwig <hch@lst.de>
Signed-off-by: Arnd Bergmann <arnd.bergmann@de.ibm.com>
Signed-off-by: Jeremy Kerr <jk@ozlabs.org>
Signed-off-by: Paul Mackerras <paulus@samba.org>
-rw-r--r-- | arch/powerpc/platforms/cell/spufs/context.c | 4 | ||||
-rw-r--r-- | arch/powerpc/platforms/cell/spufs/file.c | 56 | ||||
-rw-r--r-- | arch/powerpc/platforms/cell/spufs/spufs.h | 2 |
3 files changed, 32 insertions, 30 deletions
diff --git a/arch/powerpc/platforms/cell/spufs/context.c b/arch/powerpc/platforms/cell/spufs/context.c index 8654749e317b..7c51cb54bca1 100644 --- a/arch/powerpc/platforms/cell/spufs/context.c +++ b/arch/powerpc/platforms/cell/spufs/context.c | |||
@@ -39,7 +39,7 @@ struct spu_context *alloc_spu_context(struct spu_gang *gang) | |||
39 | if (spu_init_csa(&ctx->csa)) | 39 | if (spu_init_csa(&ctx->csa)) |
40 | goto out_free; | 40 | goto out_free; |
41 | spin_lock_init(&ctx->mmio_lock); | 41 | spin_lock_init(&ctx->mmio_lock); |
42 | spin_lock_init(&ctx->mapping_lock); | 42 | mutex_init(&ctx->mapping_lock); |
43 | kref_init(&ctx->kref); | 43 | kref_init(&ctx->kref); |
44 | mutex_init(&ctx->state_mutex); | 44 | mutex_init(&ctx->state_mutex); |
45 | mutex_init(&ctx->run_mutex); | 45 | mutex_init(&ctx->run_mutex); |
@@ -103,6 +103,7 @@ void spu_forget(struct spu_context *ctx) | |||
103 | 103 | ||
104 | void spu_unmap_mappings(struct spu_context *ctx) | 104 | void spu_unmap_mappings(struct spu_context *ctx) |
105 | { | 105 | { |
106 | mutex_lock(&ctx->mapping_lock); | ||
106 | if (ctx->local_store) | 107 | if (ctx->local_store) |
107 | unmap_mapping_range(ctx->local_store, 0, LS_SIZE, 1); | 108 | unmap_mapping_range(ctx->local_store, 0, LS_SIZE, 1); |
108 | if (ctx->mfc) | 109 | if (ctx->mfc) |
@@ -117,6 +118,7 @@ void spu_unmap_mappings(struct spu_context *ctx) | |||
117 | unmap_mapping_range(ctx->mss, 0, 0x1000, 1); | 118 | unmap_mapping_range(ctx->mss, 0, 0x1000, 1); |
118 | if (ctx->psmap) | 119 | if (ctx->psmap) |
119 | unmap_mapping_range(ctx->psmap, 0, 0x20000, 1); | 120 | unmap_mapping_range(ctx->psmap, 0, 0x20000, 1); |
121 | mutex_unlock(&ctx->mapping_lock); | ||
120 | } | 122 | } |
121 | 123 | ||
122 | /** | 124 | /** |
diff --git a/arch/powerpc/platforms/cell/spufs/file.c b/arch/powerpc/platforms/cell/spufs/file.c index 89a50110a3c5..b1e7e2f8a2e9 100644 --- a/arch/powerpc/platforms/cell/spufs/file.c +++ b/arch/powerpc/platforms/cell/spufs/file.c | |||
@@ -45,11 +45,11 @@ 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 | 47 | ||
48 | spin_lock(&ctx->mapping_lock); | 48 | mutex_lock(&ctx->mapping_lock); |
49 | file->private_data = ctx; | 49 | file->private_data = ctx; |
50 | if (!i->i_openers++) | 50 | if (!i->i_openers++) |
51 | ctx->local_store = inode->i_mapping; | 51 | ctx->local_store = inode->i_mapping; |
52 | spin_unlock(&ctx->mapping_lock); | 52 | mutex_unlock(&ctx->mapping_lock); |
53 | return 0; | 53 | return 0; |
54 | } | 54 | } |
55 | 55 | ||
@@ -59,10 +59,10 @@ spufs_mem_release(struct inode *inode, struct file *file) | |||
59 | struct spufs_inode_info *i = SPUFS_I(inode); | 59 | struct spufs_inode_info *i = SPUFS_I(inode); |
60 | struct spu_context *ctx = i->i_ctx; | 60 | struct spu_context *ctx = i->i_ctx; |
61 | 61 | ||
62 | spin_lock(&ctx->mapping_lock); | 62 | mutex_lock(&ctx->mapping_lock); |
63 | if (!--i->i_openers) | 63 | if (!--i->i_openers) |
64 | ctx->local_store = NULL; | 64 | ctx->local_store = NULL; |
65 | spin_unlock(&ctx->mapping_lock); | 65 | mutex_unlock(&ctx->mapping_lock); |
66 | return 0; | 66 | return 0; |
67 | } | 67 | } |
68 | 68 | ||
@@ -310,11 +310,11 @@ static int spufs_cntl_open(struct inode *inode, struct file *file) | |||
310 | struct spufs_inode_info *i = SPUFS_I(inode); | 310 | struct spufs_inode_info *i = SPUFS_I(inode); |
311 | struct spu_context *ctx = i->i_ctx; | 311 | struct spu_context *ctx = i->i_ctx; |
312 | 312 | ||
313 | spin_lock(&ctx->mapping_lock); | 313 | mutex_lock(&ctx->mapping_lock); |
314 | file->private_data = ctx; | 314 | file->private_data = ctx; |
315 | if (!i->i_openers++) | 315 | if (!i->i_openers++) |
316 | ctx->cntl = inode->i_mapping; | 316 | ctx->cntl = inode->i_mapping; |
317 | spin_unlock(&ctx->mapping_lock); | 317 | mutex_unlock(&ctx->mapping_lock); |
318 | return simple_attr_open(inode, file, spufs_cntl_get, | 318 | return simple_attr_open(inode, file, spufs_cntl_get, |
319 | spufs_cntl_set, "0x%08lx"); | 319 | spufs_cntl_set, "0x%08lx"); |
320 | } | 320 | } |
@@ -327,10 +327,10 @@ spufs_cntl_release(struct inode *inode, struct file *file) | |||
327 | 327 | ||
328 | simple_attr_close(inode, file); | 328 | simple_attr_close(inode, file); |
329 | 329 | ||
330 | spin_lock(&ctx->mapping_lock); | 330 | mutex_lock(&ctx->mapping_lock); |
331 | if (!--i->i_openers) | 331 | if (!--i->i_openers) |
332 | ctx->cntl = NULL; | 332 | ctx->cntl = NULL; |
333 | spin_unlock(&ctx->mapping_lock); | 333 | mutex_unlock(&ctx->mapping_lock); |
334 | return 0; | 334 | return 0; |
335 | } | 335 | } |
336 | 336 | ||
@@ -813,11 +813,11 @@ static int spufs_signal1_open(struct inode *inode, struct file *file) | |||
813 | struct spufs_inode_info *i = SPUFS_I(inode); | 813 | struct spufs_inode_info *i = SPUFS_I(inode); |
814 | struct spu_context *ctx = i->i_ctx; | 814 | struct spu_context *ctx = i->i_ctx; |
815 | 815 | ||
816 | spin_lock(&ctx->mapping_lock); | 816 | mutex_lock(&ctx->mapping_lock); |
817 | file->private_data = ctx; | 817 | file->private_data = ctx; |
818 | if (!i->i_openers++) | 818 | if (!i->i_openers++) |
819 | ctx->signal1 = inode->i_mapping; | 819 | ctx->signal1 = inode->i_mapping; |
820 | spin_unlock(&ctx->mapping_lock); | 820 | mutex_unlock(&ctx->mapping_lock); |
821 | return nonseekable_open(inode, file); | 821 | return nonseekable_open(inode, file); |
822 | } | 822 | } |
823 | 823 | ||
@@ -827,10 +827,10 @@ spufs_signal1_release(struct inode *inode, struct file *file) | |||
827 | struct spufs_inode_info *i = SPUFS_I(inode); | 827 | struct spufs_inode_info *i = SPUFS_I(inode); |
828 | struct spu_context *ctx = i->i_ctx; | 828 | struct spu_context *ctx = i->i_ctx; |
829 | 829 | ||
830 | spin_lock(&ctx->mapping_lock); | 830 | mutex_lock(&ctx->mapping_lock); |
831 | if (!--i->i_openers) | 831 | if (!--i->i_openers) |
832 | ctx->signal1 = NULL; | 832 | ctx->signal1 = NULL; |
833 | spin_unlock(&ctx->mapping_lock); | 833 | mutex_unlock(&ctx->mapping_lock); |
834 | return 0; | 834 | return 0; |
835 | } | 835 | } |
836 | 836 | ||
@@ -937,11 +937,11 @@ static int spufs_signal2_open(struct inode *inode, struct file *file) | |||
937 | struct spufs_inode_info *i = SPUFS_I(inode); | 937 | struct spufs_inode_info *i = SPUFS_I(inode); |
938 | struct spu_context *ctx = i->i_ctx; | 938 | struct spu_context *ctx = i->i_ctx; |
939 | 939 | ||
940 | spin_lock(&ctx->mapping_lock); | 940 | mutex_lock(&ctx->mapping_lock); |
941 | file->private_data = ctx; | 941 | file->private_data = ctx; |
942 | if (!i->i_openers++) | 942 | if (!i->i_openers++) |
943 | ctx->signal2 = inode->i_mapping; | 943 | ctx->signal2 = inode->i_mapping; |
944 | spin_unlock(&ctx->mapping_lock); | 944 | mutex_unlock(&ctx->mapping_lock); |
945 | return nonseekable_open(inode, file); | 945 | return nonseekable_open(inode, file); |
946 | } | 946 | } |
947 | 947 | ||
@@ -951,10 +951,10 @@ spufs_signal2_release(struct inode *inode, struct file *file) | |||
951 | struct spufs_inode_info *i = SPUFS_I(inode); | 951 | struct spufs_inode_info *i = SPUFS_I(inode); |
952 | struct spu_context *ctx = i->i_ctx; | 952 | struct spu_context *ctx = i->i_ctx; |
953 | 953 | ||
954 | spin_lock(&ctx->mapping_lock); | 954 | mutex_lock(&ctx->mapping_lock); |
955 | if (!--i->i_openers) | 955 | if (!--i->i_openers) |
956 | ctx->signal2 = NULL; | 956 | ctx->signal2 = NULL; |
957 | spin_unlock(&ctx->mapping_lock); | 957 | mutex_unlock(&ctx->mapping_lock); |
958 | return 0; | 958 | return 0; |
959 | } | 959 | } |
960 | 960 | ||
@@ -1155,10 +1155,10 @@ static int spufs_mss_open(struct inode *inode, struct file *file) | |||
1155 | 1155 | ||
1156 | file->private_data = i->i_ctx; | 1156 | file->private_data = i->i_ctx; |
1157 | 1157 | ||
1158 | spin_lock(&ctx->mapping_lock); | 1158 | mutex_lock(&ctx->mapping_lock); |
1159 | if (!i->i_openers++) | 1159 | if (!i->i_openers++) |
1160 | ctx->mss = inode->i_mapping; | 1160 | ctx->mss = inode->i_mapping; |
1161 | spin_unlock(&ctx->mapping_lock); | 1161 | mutex_unlock(&ctx->mapping_lock); |
1162 | return nonseekable_open(inode, file); | 1162 | return nonseekable_open(inode, file); |
1163 | } | 1163 | } |
1164 | 1164 | ||
@@ -1168,10 +1168,10 @@ spufs_mss_release(struct inode *inode, struct file *file) | |||
1168 | struct spufs_inode_info *i = SPUFS_I(inode); | 1168 | struct spufs_inode_info *i = SPUFS_I(inode); |
1169 | struct spu_context *ctx = i->i_ctx; | 1169 | struct spu_context *ctx = i->i_ctx; |
1170 | 1170 | ||
1171 | spin_lock(&ctx->mapping_lock); | 1171 | mutex_lock(&ctx->mapping_lock); |
1172 | if (!--i->i_openers) | 1172 | if (!--i->i_openers) |
1173 | ctx->mss = NULL; | 1173 | ctx->mss = NULL; |
1174 | spin_unlock(&ctx->mapping_lock); | 1174 | mutex_unlock(&ctx->mapping_lock); |
1175 | return 0; | 1175 | return 0; |
1176 | } | 1176 | } |
1177 | 1177 | ||
@@ -1212,11 +1212,11 @@ static int spufs_psmap_open(struct inode *inode, struct file *file) | |||
1212 | struct spufs_inode_info *i = SPUFS_I(inode); | 1212 | struct spufs_inode_info *i = SPUFS_I(inode); |
1213 | struct spu_context *ctx = i->i_ctx; | 1213 | struct spu_context *ctx = i->i_ctx; |
1214 | 1214 | ||
1215 | spin_lock(&ctx->mapping_lock); | 1215 | mutex_lock(&ctx->mapping_lock); |
1216 | file->private_data = i->i_ctx; | 1216 | file->private_data = i->i_ctx; |
1217 | if (!i->i_openers++) | 1217 | if (!i->i_openers++) |
1218 | ctx->psmap = inode->i_mapping; | 1218 | ctx->psmap = inode->i_mapping; |
1219 | spin_unlock(&ctx->mapping_lock); | 1219 | mutex_unlock(&ctx->mapping_lock); |
1220 | return nonseekable_open(inode, file); | 1220 | return nonseekable_open(inode, file); |
1221 | } | 1221 | } |
1222 | 1222 | ||
@@ -1226,10 +1226,10 @@ spufs_psmap_release(struct inode *inode, struct file *file) | |||
1226 | struct spufs_inode_info *i = SPUFS_I(inode); | 1226 | struct spufs_inode_info *i = SPUFS_I(inode); |
1227 | struct spu_context *ctx = i->i_ctx; | 1227 | struct spu_context *ctx = i->i_ctx; |
1228 | 1228 | ||
1229 | spin_lock(&ctx->mapping_lock); | 1229 | mutex_lock(&ctx->mapping_lock); |
1230 | if (!--i->i_openers) | 1230 | if (!--i->i_openers) |
1231 | ctx->psmap = NULL; | 1231 | ctx->psmap = NULL; |
1232 | spin_unlock(&ctx->mapping_lock); | 1232 | mutex_unlock(&ctx->mapping_lock); |
1233 | return 0; | 1233 | return 0; |
1234 | } | 1234 | } |
1235 | 1235 | ||
@@ -1282,11 +1282,11 @@ static int spufs_mfc_open(struct inode *inode, struct file *file) | |||
1282 | if (atomic_read(&inode->i_count) != 1) | 1282 | if (atomic_read(&inode->i_count) != 1) |
1283 | return -EBUSY; | 1283 | return -EBUSY; |
1284 | 1284 | ||
1285 | spin_lock(&ctx->mapping_lock); | 1285 | mutex_lock(&ctx->mapping_lock); |
1286 | file->private_data = ctx; | 1286 | file->private_data = ctx; |
1287 | if (!i->i_openers++) | 1287 | if (!i->i_openers++) |
1288 | ctx->mfc = inode->i_mapping; | 1288 | ctx->mfc = inode->i_mapping; |
1289 | spin_unlock(&ctx->mapping_lock); | 1289 | mutex_unlock(&ctx->mapping_lock); |
1290 | return nonseekable_open(inode, file); | 1290 | return nonseekable_open(inode, file); |
1291 | } | 1291 | } |
1292 | 1292 | ||
@@ -1296,10 +1296,10 @@ spufs_mfc_release(struct inode *inode, struct file *file) | |||
1296 | struct spufs_inode_info *i = SPUFS_I(inode); | 1296 | struct spufs_inode_info *i = SPUFS_I(inode); |
1297 | struct spu_context *ctx = i->i_ctx; | 1297 | struct spu_context *ctx = i->i_ctx; |
1298 | 1298 | ||
1299 | spin_lock(&ctx->mapping_lock); | 1299 | mutex_lock(&ctx->mapping_lock); |
1300 | if (!--i->i_openers) | 1300 | if (!--i->i_openers) |
1301 | ctx->mfc = NULL; | 1301 | ctx->mfc = NULL; |
1302 | spin_unlock(&ctx->mapping_lock); | 1302 | mutex_unlock(&ctx->mapping_lock); |
1303 | return 0; | 1303 | return 0; |
1304 | } | 1304 | } |
1305 | 1305 | ||
diff --git a/arch/powerpc/platforms/cell/spufs/spufs.h b/arch/powerpc/platforms/cell/spufs/spufs.h index 0a947fd7de57..47617e8014a5 100644 --- a/arch/powerpc/platforms/cell/spufs/spufs.h +++ b/arch/powerpc/platforms/cell/spufs/spufs.h | |||
@@ -55,7 +55,7 @@ struct spu_context { | |||
55 | struct address_space *signal2; /* 'signal2' area mappings. */ | 55 | struct address_space *signal2; /* 'signal2' area mappings. */ |
56 | struct address_space *mss; /* 'mss' area mappings. */ | 56 | struct address_space *mss; /* 'mss' area mappings. */ |
57 | struct address_space *psmap; /* 'psmap' area mappings. */ | 57 | struct address_space *psmap; /* 'psmap' area mappings. */ |
58 | spinlock_t mapping_lock; | 58 | struct mutex mapping_lock; |
59 | u64 object_id; /* user space pointer for oprofile */ | 59 | u64 object_id; /* user space pointer for oprofile */ |
60 | 60 | ||
61 | enum { SPU_STATE_RUNNABLE, SPU_STATE_SAVED } state; | 61 | enum { SPU_STATE_RUNNABLE, SPU_STATE_SAVED } state; |