diff options
Diffstat (limited to 'arch/powerpc/platforms/cell/spufs')
-rw-r--r-- | arch/powerpc/platforms/cell/spufs/file.c | 22 | ||||
-rw-r--r-- | arch/powerpc/platforms/cell/spufs/hw_ops.c | 5 | ||||
-rw-r--r-- | arch/powerpc/platforms/cell/spufs/inode.c | 17 | ||||
-rw-r--r-- | arch/powerpc/platforms/cell/spufs/run.c | 10 | ||||
-rw-r--r-- | arch/powerpc/platforms/cell/spufs/spufs.h | 1 | ||||
-rw-r--r-- | arch/powerpc/platforms/cell/spufs/switch.c | 50 |
6 files changed, 99 insertions, 6 deletions
diff --git a/arch/powerpc/platforms/cell/spufs/file.c b/arch/powerpc/platforms/cell/spufs/file.c index 0de8e114e6b6..8ca330671ad1 100644 --- a/arch/powerpc/platforms/cell/spufs/file.c +++ b/arch/powerpc/platforms/cell/spufs/file.c | |||
@@ -1531,3 +1531,25 @@ struct tree_descr spufs_dir_contents[] = { | |||
1531 | { "object-id", &spufs_object_id_ops, 0666, }, | 1531 | { "object-id", &spufs_object_id_ops, 0666, }, |
1532 | {}, | 1532 | {}, |
1533 | }; | 1533 | }; |
1534 | |||
1535 | struct tree_descr spufs_dir_nosched_contents[] = { | ||
1536 | { "mem", &spufs_mem_fops, 0666, }, | ||
1537 | { "mbox", &spufs_mbox_fops, 0444, }, | ||
1538 | { "ibox", &spufs_ibox_fops, 0444, }, | ||
1539 | { "wbox", &spufs_wbox_fops, 0222, }, | ||
1540 | { "mbox_stat", &spufs_mbox_stat_fops, 0444, }, | ||
1541 | { "ibox_stat", &spufs_ibox_stat_fops, 0444, }, | ||
1542 | { "wbox_stat", &spufs_wbox_stat_fops, 0444, }, | ||
1543 | { "signal1", &spufs_signal1_fops, 0666, }, | ||
1544 | { "signal2", &spufs_signal2_fops, 0666, }, | ||
1545 | { "signal1_type", &spufs_signal1_type, 0666, }, | ||
1546 | { "signal2_type", &spufs_signal2_type, 0666, }, | ||
1547 | { "mss", &spufs_mss_fops, 0666, }, | ||
1548 | { "mfc", &spufs_mfc_fops, 0666, }, | ||
1549 | { "cntl", &spufs_cntl_fops, 0666, }, | ||
1550 | { "npc", &spufs_npc_ops, 0666, }, | ||
1551 | { "psmap", &spufs_psmap_fops, 0666, }, | ||
1552 | { "phys-id", &spufs_id_ops, 0666, }, | ||
1553 | { "object-id", &spufs_object_id_ops, 0666, }, | ||
1554 | {}, | ||
1555 | }; | ||
diff --git a/arch/powerpc/platforms/cell/spufs/hw_ops.c b/arch/powerpc/platforms/cell/spufs/hw_ops.c index efc452e71ab0..2ad534a04be8 100644 --- a/arch/powerpc/platforms/cell/spufs/hw_ops.c +++ b/arch/powerpc/platforms/cell/spufs/hw_ops.c | |||
@@ -219,8 +219,11 @@ static char *spu_hw_get_ls(struct spu_context *ctx) | |||
219 | 219 | ||
220 | static void spu_hw_runcntl_write(struct spu_context *ctx, u32 val) | 220 | static void spu_hw_runcntl_write(struct spu_context *ctx, u32 val) |
221 | { | 221 | { |
222 | eieio(); | 222 | spin_lock_irq(&ctx->spu->register_lock); |
223 | if (val & SPU_RUNCNTL_ISOLATE) | ||
224 | out_be64(&ctx->spu->priv2->spu_privcntl_RW, 4LL); | ||
223 | out_be32(&ctx->spu->problem->spu_runcntl_RW, val); | 225 | out_be32(&ctx->spu->problem->spu_runcntl_RW, val); |
226 | spin_unlock_irq(&ctx->spu->register_lock); | ||
224 | } | 227 | } |
225 | 228 | ||
226 | static void spu_hw_runcntl_stop(struct spu_context *ctx) | 229 | static void spu_hw_runcntl_stop(struct spu_context *ctx) |
diff --git a/arch/powerpc/platforms/cell/spufs/inode.c b/arch/powerpc/platforms/cell/spufs/inode.c index 427d00a4f6a0..787ae71a6859 100644 --- a/arch/powerpc/platforms/cell/spufs/inode.c +++ b/arch/powerpc/platforms/cell/spufs/inode.c | |||
@@ -258,7 +258,12 @@ spufs_mkdir(struct inode *dir, struct dentry *dentry, unsigned int flags, | |||
258 | 258 | ||
259 | inode->i_op = &spufs_dir_inode_operations; | 259 | inode->i_op = &spufs_dir_inode_operations; |
260 | inode->i_fop = &simple_dir_operations; | 260 | inode->i_fop = &simple_dir_operations; |
261 | ret = spufs_fill_dir(dentry, spufs_dir_contents, mode, ctx); | 261 | if (flags & SPU_CREATE_NOSCHED) |
262 | ret = spufs_fill_dir(dentry, spufs_dir_nosched_contents, | ||
263 | mode, ctx); | ||
264 | else | ||
265 | ret = spufs_fill_dir(dentry, spufs_dir_contents, mode, ctx); | ||
266 | |||
262 | if (ret) | 267 | if (ret) |
263 | goto out_free_ctx; | 268 | goto out_free_ctx; |
264 | 269 | ||
@@ -307,6 +312,16 @@ static int spufs_create_context(struct inode *inode, | |||
307 | { | 312 | { |
308 | int ret; | 313 | int ret; |
309 | 314 | ||
315 | ret = -EPERM; | ||
316 | if ((flags & SPU_CREATE_NOSCHED) && | ||
317 | !capable(CAP_SYS_NICE)) | ||
318 | goto out_unlock; | ||
319 | |||
320 | ret = -EINVAL; | ||
321 | if ((flags & (SPU_CREATE_NOSCHED | SPU_CREATE_ISOLATE)) | ||
322 | == SPU_CREATE_ISOLATE) | ||
323 | goto out_unlock; | ||
324 | |||
310 | ret = spufs_mkdir(inode, dentry, flags, mode & S_IRWXUGO); | 325 | ret = spufs_mkdir(inode, dentry, flags, mode & S_IRWXUGO); |
311 | if (ret) | 326 | if (ret) |
312 | goto out_unlock; | 327 | goto out_unlock; |
diff --git a/arch/powerpc/platforms/cell/spufs/run.c b/arch/powerpc/platforms/cell/spufs/run.c index 63df8cf4ba16..0c03a04b6a30 100644 --- a/arch/powerpc/platforms/cell/spufs/run.c +++ b/arch/powerpc/platforms/cell/spufs/run.c | |||
@@ -51,11 +51,17 @@ static inline int spu_stopped(struct spu_context *ctx, u32 * stat) | |||
51 | static inline int spu_run_init(struct spu_context *ctx, u32 * npc) | 51 | static inline int spu_run_init(struct spu_context *ctx, u32 * npc) |
52 | { | 52 | { |
53 | int ret; | 53 | int ret; |
54 | unsigned long runcntl = SPU_RUNCNTL_RUNNABLE; | ||
54 | 55 | ||
55 | if ((ret = spu_acquire_runnable(ctx)) != 0) | 56 | if ((ret = spu_acquire_runnable(ctx)) != 0) |
56 | return ret; | 57 | return ret; |
57 | ctx->ops->npc_write(ctx, *npc); | 58 | |
58 | ctx->ops->runcntl_write(ctx, SPU_RUNCNTL_RUNNABLE); | 59 | if (ctx->flags & SPU_CREATE_ISOLATE) |
60 | runcntl |= SPU_RUNCNTL_ISOLATE; | ||
61 | else | ||
62 | ctx->ops->npc_write(ctx, *npc); | ||
63 | |||
64 | ctx->ops->runcntl_write(ctx, runcntl); | ||
59 | return 0; | 65 | return 0; |
60 | } | 66 | } |
61 | 67 | ||
diff --git a/arch/powerpc/platforms/cell/spufs/spufs.h b/arch/powerpc/platforms/cell/spufs/spufs.h index a0f55ca2d488..b17b809ecd77 100644 --- a/arch/powerpc/platforms/cell/spufs/spufs.h +++ b/arch/powerpc/platforms/cell/spufs/spufs.h | |||
@@ -135,6 +135,7 @@ struct spufs_inode_info { | |||
135 | container_of(inode, struct spufs_inode_info, vfs_inode) | 135 | container_of(inode, struct spufs_inode_info, vfs_inode) |
136 | 136 | ||
137 | extern struct tree_descr spufs_dir_contents[]; | 137 | extern struct tree_descr spufs_dir_contents[]; |
138 | extern struct tree_descr spufs_dir_nosched_contents[]; | ||
138 | 139 | ||
139 | /* system call implementation */ | 140 | /* system call implementation */ |
140 | long spufs_run_spu(struct file *file, | 141 | long spufs_run_spu(struct file *file, |
diff --git a/arch/powerpc/platforms/cell/spufs/switch.c b/arch/powerpc/platforms/cell/spufs/switch.c index b85347ff6b22..b47fb50ac2c1 100644 --- a/arch/powerpc/platforms/cell/spufs/switch.c +++ b/arch/powerpc/platforms/cell/spufs/switch.c | |||
@@ -1916,6 +1916,51 @@ static void save_lscsa(struct spu_state *prev, struct spu *spu) | |||
1916 | wait_spu_stopped(prev, spu); /* Step 57. */ | 1916 | wait_spu_stopped(prev, spu); /* Step 57. */ |
1917 | } | 1917 | } |
1918 | 1918 | ||
1919 | static void force_spu_isolate_exit(struct spu *spu) | ||
1920 | { | ||
1921 | struct spu_problem __iomem *prob = spu->problem; | ||
1922 | struct spu_priv2 __iomem *priv2 = spu->priv2; | ||
1923 | |||
1924 | /* Stop SPE execution and wait for completion. */ | ||
1925 | out_be32(&prob->spu_runcntl_RW, SPU_RUNCNTL_STOP); | ||
1926 | iobarrier_rw(); | ||
1927 | POLL_WHILE_TRUE(in_be32(&prob->spu_status_R) & SPU_STATUS_RUNNING); | ||
1928 | |||
1929 | /* Restart SPE master runcntl. */ | ||
1930 | spu_mfc_sr1_set(spu, MFC_STATE1_MASTER_RUN_CONTROL_MASK); | ||
1931 | iobarrier_w(); | ||
1932 | |||
1933 | /* Initiate isolate exit request and wait for completion. */ | ||
1934 | out_be64(&priv2->spu_privcntl_RW, 4LL); | ||
1935 | iobarrier_w(); | ||
1936 | out_be32(&prob->spu_runcntl_RW, 2); | ||
1937 | iobarrier_rw(); | ||
1938 | POLL_WHILE_FALSE((in_be32(&prob->spu_status_R) | ||
1939 | & SPU_STATUS_STOPPED_BY_STOP)); | ||
1940 | |||
1941 | /* Reset load request to normal. */ | ||
1942 | out_be64(&priv2->spu_privcntl_RW, SPU_PRIVCNT_LOAD_REQUEST_NORMAL); | ||
1943 | iobarrier_w(); | ||
1944 | } | ||
1945 | |||
1946 | /** | ||
1947 | * stop_spu_isolate | ||
1948 | * Check SPU run-control state and force isolated | ||
1949 | * exit function as necessary. | ||
1950 | */ | ||
1951 | static void stop_spu_isolate(struct spu *spu) | ||
1952 | { | ||
1953 | struct spu_problem __iomem *prob = spu->problem; | ||
1954 | |||
1955 | if (in_be32(&prob->spu_status_R) & SPU_STATUS_ISOLATED_STATE) { | ||
1956 | /* The SPU is in isolated state; the only way | ||
1957 | * to get it out is to perform an isolated | ||
1958 | * exit (clean) operation. | ||
1959 | */ | ||
1960 | force_spu_isolate_exit(spu); | ||
1961 | } | ||
1962 | } | ||
1963 | |||
1919 | static void harvest(struct spu_state *prev, struct spu *spu) | 1964 | static void harvest(struct spu_state *prev, struct spu *spu) |
1920 | { | 1965 | { |
1921 | /* | 1966 | /* |
@@ -1928,6 +1973,7 @@ static void harvest(struct spu_state *prev, struct spu *spu) | |||
1928 | inhibit_user_access(prev, spu); /* Step 3. */ | 1973 | inhibit_user_access(prev, spu); /* Step 3. */ |
1929 | terminate_spu_app(prev, spu); /* Step 4. */ | 1974 | terminate_spu_app(prev, spu); /* Step 4. */ |
1930 | set_switch_pending(prev, spu); /* Step 5. */ | 1975 | set_switch_pending(prev, spu); /* Step 5. */ |
1976 | stop_spu_isolate(spu); /* NEW. */ | ||
1931 | remove_other_spu_access(prev, spu); /* Step 6. */ | 1977 | remove_other_spu_access(prev, spu); /* Step 6. */ |
1932 | suspend_mfc(prev, spu); /* Step 7. */ | 1978 | suspend_mfc(prev, spu); /* Step 7. */ |
1933 | wait_suspend_mfc_complete(prev, spu); /* Step 8. */ | 1979 | wait_suspend_mfc_complete(prev, spu); /* Step 8. */ |
@@ -2096,11 +2142,11 @@ int spu_save(struct spu_state *prev, struct spu *spu) | |||
2096 | acquire_spu_lock(spu); /* Step 1. */ | 2142 | acquire_spu_lock(spu); /* Step 1. */ |
2097 | rc = __do_spu_save(prev, spu); /* Steps 2-53. */ | 2143 | rc = __do_spu_save(prev, spu); /* Steps 2-53. */ |
2098 | release_spu_lock(spu); | 2144 | release_spu_lock(spu); |
2099 | if (rc) { | 2145 | if (rc != 0 && rc != 2 && rc != 6) { |
2100 | panic("%s failed on SPU[%d], rc=%d.\n", | 2146 | panic("%s failed on SPU[%d], rc=%d.\n", |
2101 | __func__, spu->number, rc); | 2147 | __func__, spu->number, rc); |
2102 | } | 2148 | } |
2103 | return rc; | 2149 | return 0; |
2104 | } | 2150 | } |
2105 | EXPORT_SYMBOL_GPL(spu_save); | 2151 | EXPORT_SYMBOL_GPL(spu_save); |
2106 | 2152 | ||