diff options
Diffstat (limited to 'arch')
-rw-r--r-- | arch/powerpc/platforms/cell/spufs/context.c | 1 | ||||
-rw-r--r-- | arch/powerpc/platforms/cell/spufs/file.c | 147 | ||||
-rw-r--r-- | arch/powerpc/platforms/cell/spufs/inode.c | 1 | ||||
-rw-r--r-- | arch/powerpc/platforms/cell/spufs/spufs.h | 12 |
4 files changed, 148 insertions, 13 deletions
diff --git a/arch/powerpc/platforms/cell/spufs/context.c b/arch/powerpc/platforms/cell/spufs/context.c index 04ad2e364e97..b3954aba424e 100644 --- a/arch/powerpc/platforms/cell/spufs/context.c +++ b/arch/powerpc/platforms/cell/spufs/context.c | |||
@@ -41,6 +41,7 @@ struct spu_context *alloc_spu_context(struct spu_gang *gang) | |||
41 | goto out_free; | 41 | goto out_free; |
42 | } | 42 | } |
43 | spin_lock_init(&ctx->mmio_lock); | 43 | spin_lock_init(&ctx->mmio_lock); |
44 | spin_lock_init(&ctx->mapping_lock); | ||
44 | kref_init(&ctx->kref); | 45 | kref_init(&ctx->kref); |
45 | mutex_init(&ctx->state_mutex); | 46 | mutex_init(&ctx->state_mutex); |
46 | init_MUTEX(&ctx->run_sema); | 47 | init_MUTEX(&ctx->run_sema); |
diff --git a/arch/powerpc/platforms/cell/spufs/file.c b/arch/powerpc/platforms/cell/spufs/file.c index 505266a568d4..deb340e6e0ae 100644 --- a/arch/powerpc/platforms/cell/spufs/file.c +++ b/arch/powerpc/platforms/cell/spufs/file.c | |||
@@ -44,8 +44,26 @@ spufs_mem_open(struct inode *inode, struct file *file) | |||
44 | { | 44 | { |
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 | |||
48 | spin_lock(&ctx->mapping_lock); | ||
47 | file->private_data = ctx; | 49 | file->private_data = ctx; |
48 | ctx->local_store = inode->i_mapping; | 50 | if (!i->i_openers++) |
51 | ctx->local_store = inode->i_mapping; | ||
52 | spin_unlock(&ctx->mapping_lock); | ||
53 | smp_wmb(); | ||
54 | return 0; | ||
55 | } | ||
56 | |||
57 | static int | ||
58 | spufs_mem_release(struct inode *inode, struct file *file) | ||
59 | { | ||
60 | struct spufs_inode_info *i = SPUFS_I(inode); | ||
61 | struct spu_context *ctx = i->i_ctx; | ||
62 | |||
63 | spin_lock(&ctx->mapping_lock); | ||
64 | if (!--i->i_openers) | ||
65 | ctx->local_store = NULL; | ||
66 | spin_unlock(&ctx->mapping_lock); | ||
49 | smp_wmb(); | 67 | smp_wmb(); |
50 | return 0; | 68 | return 0; |
51 | } | 69 | } |
@@ -149,6 +167,7 @@ spufs_mem_mmap(struct file *file, struct vm_area_struct *vma) | |||
149 | 167 | ||
150 | static const struct file_operations spufs_mem_fops = { | 168 | static const struct file_operations spufs_mem_fops = { |
151 | .open = spufs_mem_open, | 169 | .open = spufs_mem_open, |
170 | .release = spufs_mem_release, | ||
152 | .read = spufs_mem_read, | 171 | .read = spufs_mem_read, |
153 | .write = spufs_mem_write, | 172 | .write = spufs_mem_write, |
154 | .llseek = generic_file_llseek, | 173 | .llseek = generic_file_llseek, |
@@ -238,16 +257,35 @@ static int spufs_cntl_open(struct inode *inode, struct file *file) | |||
238 | struct spufs_inode_info *i = SPUFS_I(inode); | 257 | struct spufs_inode_info *i = SPUFS_I(inode); |
239 | struct spu_context *ctx = i->i_ctx; | 258 | struct spu_context *ctx = i->i_ctx; |
240 | 259 | ||
260 | spin_lock(&ctx->mapping_lock); | ||
241 | file->private_data = ctx; | 261 | file->private_data = ctx; |
242 | ctx->cntl = inode->i_mapping; | 262 | if (!i->i_openers++) |
263 | ctx->cntl = inode->i_mapping; | ||
264 | spin_unlock(&ctx->mapping_lock); | ||
243 | smp_wmb(); | 265 | smp_wmb(); |
244 | return simple_attr_open(inode, file, spufs_cntl_get, | 266 | return simple_attr_open(inode, file, spufs_cntl_get, |
245 | spufs_cntl_set, "0x%08lx"); | 267 | spufs_cntl_set, "0x%08lx"); |
246 | } | 268 | } |
247 | 269 | ||
270 | static int | ||
271 | spufs_cntl_release(struct inode *inode, struct file *file) | ||
272 | { | ||
273 | struct spufs_inode_info *i = SPUFS_I(inode); | ||
274 | struct spu_context *ctx = i->i_ctx; | ||
275 | |||
276 | simple_attr_close(inode, file); | ||
277 | |||
278 | spin_lock(&ctx->mapping_lock); | ||
279 | if (!--i->i_openers) | ||
280 | ctx->cntl = NULL; | ||
281 | spin_unlock(&ctx->mapping_lock); | ||
282 | smp_wmb(); | ||
283 | return 0; | ||
284 | } | ||
285 | |||
248 | static const struct file_operations spufs_cntl_fops = { | 286 | static const struct file_operations spufs_cntl_fops = { |
249 | .open = spufs_cntl_open, | 287 | .open = spufs_cntl_open, |
250 | .release = simple_attr_close, | 288 | .release = spufs_cntl_release, |
251 | .read = simple_attr_read, | 289 | .read = simple_attr_read, |
252 | .write = simple_attr_write, | 290 | .write = simple_attr_write, |
253 | .mmap = spufs_cntl_mmap, | 291 | .mmap = spufs_cntl_mmap, |
@@ -723,12 +761,30 @@ static int spufs_signal1_open(struct inode *inode, struct file *file) | |||
723 | { | 761 | { |
724 | struct spufs_inode_info *i = SPUFS_I(inode); | 762 | struct spufs_inode_info *i = SPUFS_I(inode); |
725 | struct spu_context *ctx = i->i_ctx; | 763 | struct spu_context *ctx = i->i_ctx; |
764 | |||
765 | spin_lock(&ctx->mapping_lock); | ||
726 | file->private_data = ctx; | 766 | file->private_data = ctx; |
727 | ctx->signal1 = inode->i_mapping; | 767 | if (!i->i_openers++) |
768 | ctx->signal1 = inode->i_mapping; | ||
769 | spin_unlock(&ctx->mapping_lock); | ||
728 | smp_wmb(); | 770 | smp_wmb(); |
729 | return nonseekable_open(inode, file); | 771 | return nonseekable_open(inode, file); |
730 | } | 772 | } |
731 | 773 | ||
774 | static int | ||
775 | spufs_signal1_release(struct inode *inode, struct file *file) | ||
776 | { | ||
777 | struct spufs_inode_info *i = SPUFS_I(inode); | ||
778 | struct spu_context *ctx = i->i_ctx; | ||
779 | |||
780 | spin_lock(&ctx->mapping_lock); | ||
781 | if (!--i->i_openers) | ||
782 | ctx->signal1 = NULL; | ||
783 | spin_unlock(&ctx->mapping_lock); | ||
784 | smp_wmb(); | ||
785 | return 0; | ||
786 | } | ||
787 | |||
732 | static ssize_t __spufs_signal1_read(struct spu_context *ctx, char __user *buf, | 788 | static ssize_t __spufs_signal1_read(struct spu_context *ctx, char __user *buf, |
733 | size_t len, loff_t *pos) | 789 | size_t len, loff_t *pos) |
734 | { | 790 | { |
@@ -821,6 +877,7 @@ static int spufs_signal1_mmap(struct file *file, struct vm_area_struct *vma) | |||
821 | 877 | ||
822 | static const struct file_operations spufs_signal1_fops = { | 878 | static const struct file_operations spufs_signal1_fops = { |
823 | .open = spufs_signal1_open, | 879 | .open = spufs_signal1_open, |
880 | .release = spufs_signal1_release, | ||
824 | .read = spufs_signal1_read, | 881 | .read = spufs_signal1_read, |
825 | .write = spufs_signal1_write, | 882 | .write = spufs_signal1_write, |
826 | .mmap = spufs_signal1_mmap, | 883 | .mmap = spufs_signal1_mmap, |
@@ -830,12 +887,30 @@ static int spufs_signal2_open(struct inode *inode, struct file *file) | |||
830 | { | 887 | { |
831 | struct spufs_inode_info *i = SPUFS_I(inode); | 888 | struct spufs_inode_info *i = SPUFS_I(inode); |
832 | struct spu_context *ctx = i->i_ctx; | 889 | struct spu_context *ctx = i->i_ctx; |
890 | |||
891 | spin_lock(&ctx->mapping_lock); | ||
833 | file->private_data = ctx; | 892 | file->private_data = ctx; |
834 | ctx->signal2 = inode->i_mapping; | 893 | if (!i->i_openers++) |
894 | ctx->signal2 = inode->i_mapping; | ||
895 | spin_unlock(&ctx->mapping_lock); | ||
835 | smp_wmb(); | 896 | smp_wmb(); |
836 | return nonseekable_open(inode, file); | 897 | return nonseekable_open(inode, file); |
837 | } | 898 | } |
838 | 899 | ||
900 | static int | ||
901 | spufs_signal2_release(struct inode *inode, struct file *file) | ||
902 | { | ||
903 | struct spufs_inode_info *i = SPUFS_I(inode); | ||
904 | struct spu_context *ctx = i->i_ctx; | ||
905 | |||
906 | spin_lock(&ctx->mapping_lock); | ||
907 | if (!--i->i_openers) | ||
908 | ctx->signal2 = NULL; | ||
909 | spin_unlock(&ctx->mapping_lock); | ||
910 | smp_wmb(); | ||
911 | return 0; | ||
912 | } | ||
913 | |||
839 | static ssize_t __spufs_signal2_read(struct spu_context *ctx, char __user *buf, | 914 | static ssize_t __spufs_signal2_read(struct spu_context *ctx, char __user *buf, |
840 | size_t len, loff_t *pos) | 915 | size_t len, loff_t *pos) |
841 | { | 916 | { |
@@ -932,6 +1007,7 @@ static int spufs_signal2_mmap(struct file *file, struct vm_area_struct *vma) | |||
932 | 1007 | ||
933 | static const struct file_operations spufs_signal2_fops = { | 1008 | static const struct file_operations spufs_signal2_fops = { |
934 | .open = spufs_signal2_open, | 1009 | .open = spufs_signal2_open, |
1010 | .release = spufs_signal2_release, | ||
935 | .read = spufs_signal2_read, | 1011 | .read = spufs_signal2_read, |
936 | .write = spufs_signal2_write, | 1012 | .write = spufs_signal2_write, |
937 | .mmap = spufs_signal2_mmap, | 1013 | .mmap = spufs_signal2_mmap, |
@@ -1031,13 +1107,32 @@ static int spufs_mss_open(struct inode *inode, struct file *file) | |||
1031 | struct spu_context *ctx = i->i_ctx; | 1107 | struct spu_context *ctx = i->i_ctx; |
1032 | 1108 | ||
1033 | file->private_data = i->i_ctx; | 1109 | file->private_data = i->i_ctx; |
1034 | ctx->mss = inode->i_mapping; | 1110 | |
1111 | spin_lock(&ctx->mapping_lock); | ||
1112 | if (!i->i_openers++) | ||
1113 | ctx->mss = inode->i_mapping; | ||
1114 | spin_unlock(&ctx->mapping_lock); | ||
1035 | smp_wmb(); | 1115 | smp_wmb(); |
1036 | return nonseekable_open(inode, file); | 1116 | return nonseekable_open(inode, file); |
1037 | } | 1117 | } |
1038 | 1118 | ||
1119 | static int | ||
1120 | spufs_mss_release(struct inode *inode, struct file *file) | ||
1121 | { | ||
1122 | struct spufs_inode_info *i = SPUFS_I(inode); | ||
1123 | struct spu_context *ctx = i->i_ctx; | ||
1124 | |||
1125 | spin_lock(&ctx->mapping_lock); | ||
1126 | if (!--i->i_openers) | ||
1127 | ctx->mss = NULL; | ||
1128 | spin_unlock(&ctx->mapping_lock); | ||
1129 | smp_wmb(); | ||
1130 | return 0; | ||
1131 | } | ||
1132 | |||
1039 | static const struct file_operations spufs_mss_fops = { | 1133 | static const struct file_operations spufs_mss_fops = { |
1040 | .open = spufs_mss_open, | 1134 | .open = spufs_mss_open, |
1135 | .release = spufs_mss_release, | ||
1041 | .mmap = spufs_mss_mmap, | 1136 | .mmap = spufs_mss_mmap, |
1042 | }; | 1137 | }; |
1043 | 1138 | ||
@@ -1072,14 +1167,32 @@ static int spufs_psmap_open(struct inode *inode, struct file *file) | |||
1072 | struct spufs_inode_info *i = SPUFS_I(inode); | 1167 | struct spufs_inode_info *i = SPUFS_I(inode); |
1073 | struct spu_context *ctx = i->i_ctx; | 1168 | struct spu_context *ctx = i->i_ctx; |
1074 | 1169 | ||
1170 | spin_lock(&ctx->mapping_lock); | ||
1075 | file->private_data = i->i_ctx; | 1171 | file->private_data = i->i_ctx; |
1076 | ctx->psmap = inode->i_mapping; | 1172 | if (!i->i_openers++) |
1173 | ctx->psmap = inode->i_mapping; | ||
1174 | spin_unlock(&ctx->mapping_lock); | ||
1077 | smp_wmb(); | 1175 | smp_wmb(); |
1078 | return nonseekable_open(inode, file); | 1176 | return nonseekable_open(inode, file); |
1079 | } | 1177 | } |
1080 | 1178 | ||
1179 | static int | ||
1180 | spufs_psmap_release(struct inode *inode, struct file *file) | ||
1181 | { | ||
1182 | struct spufs_inode_info *i = SPUFS_I(inode); | ||
1183 | struct spu_context *ctx = i->i_ctx; | ||
1184 | |||
1185 | spin_lock(&ctx->mapping_lock); | ||
1186 | if (!--i->i_openers) | ||
1187 | ctx->psmap = NULL; | ||
1188 | spin_unlock(&ctx->mapping_lock); | ||
1189 | smp_wmb(); | ||
1190 | return 0; | ||
1191 | } | ||
1192 | |||
1081 | static const struct file_operations spufs_psmap_fops = { | 1193 | static const struct file_operations spufs_psmap_fops = { |
1082 | .open = spufs_psmap_open, | 1194 | .open = spufs_psmap_open, |
1195 | .release = spufs_psmap_release, | ||
1083 | .mmap = spufs_psmap_mmap, | 1196 | .mmap = spufs_psmap_mmap, |
1084 | }; | 1197 | }; |
1085 | 1198 | ||
@@ -1126,12 +1239,29 @@ static int spufs_mfc_open(struct inode *inode, struct file *file) | |||
1126 | if (atomic_read(&inode->i_count) != 1) | 1239 | if (atomic_read(&inode->i_count) != 1) |
1127 | return -EBUSY; | 1240 | return -EBUSY; |
1128 | 1241 | ||
1242 | spin_lock(&ctx->mapping_lock); | ||
1129 | file->private_data = ctx; | 1243 | file->private_data = ctx; |
1130 | ctx->mfc = inode->i_mapping; | 1244 | if (!i->i_openers++) |
1245 | ctx->mfc = inode->i_mapping; | ||
1246 | spin_unlock(&ctx->mapping_lock); | ||
1131 | smp_wmb(); | 1247 | smp_wmb(); |
1132 | return nonseekable_open(inode, file); | 1248 | return nonseekable_open(inode, file); |
1133 | } | 1249 | } |
1134 | 1250 | ||
1251 | static int | ||
1252 | spufs_mfc_release(struct inode *inode, struct file *file) | ||
1253 | { | ||
1254 | struct spufs_inode_info *i = SPUFS_I(inode); | ||
1255 | struct spu_context *ctx = i->i_ctx; | ||
1256 | |||
1257 | spin_lock(&ctx->mapping_lock); | ||
1258 | if (!--i->i_openers) | ||
1259 | ctx->mfc = NULL; | ||
1260 | spin_unlock(&ctx->mapping_lock); | ||
1261 | smp_wmb(); | ||
1262 | return 0; | ||
1263 | } | ||
1264 | |||
1135 | /* interrupt-level mfc callback function. */ | 1265 | /* interrupt-level mfc callback function. */ |
1136 | void spufs_mfc_callback(struct spu *spu) | 1266 | void spufs_mfc_callback(struct spu *spu) |
1137 | { | 1267 | { |
@@ -1399,6 +1529,7 @@ static int spufs_mfc_fasync(int fd, struct file *file, int on) | |||
1399 | 1529 | ||
1400 | static const struct file_operations spufs_mfc_fops = { | 1530 | static const struct file_operations spufs_mfc_fops = { |
1401 | .open = spufs_mfc_open, | 1531 | .open = spufs_mfc_open, |
1532 | .release = spufs_mfc_release, | ||
1402 | .read = spufs_mfc_read, | 1533 | .read = spufs_mfc_read, |
1403 | .write = spufs_mfc_write, | 1534 | .write = spufs_mfc_write, |
1404 | .poll = spufs_mfc_poll, | 1535 | .poll = spufs_mfc_poll, |
diff --git a/arch/powerpc/platforms/cell/spufs/inode.c b/arch/powerpc/platforms/cell/spufs/inode.c index e3f4ee97c913..423596a6b995 100644 --- a/arch/powerpc/platforms/cell/spufs/inode.c +++ b/arch/powerpc/platforms/cell/spufs/inode.c | |||
@@ -54,6 +54,7 @@ spufs_alloc_inode(struct super_block *sb) | |||
54 | 54 | ||
55 | ei->i_gang = NULL; | 55 | ei->i_gang = NULL; |
56 | ei->i_ctx = NULL; | 56 | ei->i_ctx = NULL; |
57 | ei->i_openers = 0; | ||
57 | 58 | ||
58 | return &ei->vfs_inode; | 59 | return &ei->vfs_inode; |
59 | } | 60 | } |
diff --git a/arch/powerpc/platforms/cell/spufs/spufs.h b/arch/powerpc/platforms/cell/spufs/spufs.h index f418378abdff..0fb366d9d257 100644 --- a/arch/powerpc/platforms/cell/spufs/spufs.h +++ b/arch/powerpc/platforms/cell/spufs/spufs.h | |||
@@ -50,11 +50,12 @@ struct spu_context { | |||
50 | spinlock_t mmio_lock; /* protects mmio access */ | 50 | spinlock_t mmio_lock; /* protects mmio access */ |
51 | struct address_space *local_store; /* local store mapping. */ | 51 | struct address_space *local_store; /* local store mapping. */ |
52 | struct address_space *mfc; /* 'mfc' area mappings. */ | 52 | struct address_space *mfc; /* 'mfc' area mappings. */ |
53 | struct address_space *cntl; /* 'control' area mappings. */ | 53 | struct address_space *cntl; /* 'control' area mappings. */ |
54 | struct address_space *signal1; /* 'signal1' area mappings. */ | 54 | struct address_space *signal1; /* 'signal1' area mappings. */ |
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 | u64 object_id; /* user space pointer for oprofile */ | 59 | u64 object_id; /* user space pointer for oprofile */ |
59 | 60 | ||
60 | enum { SPU_STATE_RUNNABLE, SPU_STATE_SAVED } state; | 61 | enum { SPU_STATE_RUNNABLE, SPU_STATE_SAVED } state; |
@@ -149,6 +150,7 @@ struct spufs_inode_info { | |||
149 | struct spu_context *i_ctx; | 150 | struct spu_context *i_ctx; |
150 | struct spu_gang *i_gang; | 151 | struct spu_gang *i_gang; |
151 | struct inode vfs_inode; | 152 | struct inode vfs_inode; |
153 | int i_openers; | ||
152 | }; | 154 | }; |
153 | #define SPUFS_I(inode) \ | 155 | #define SPUFS_I(inode) \ |
154 | container_of(inode, struct spufs_inode_info, vfs_inode) | 156 | container_of(inode, struct spufs_inode_info, vfs_inode) |