aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--arch/powerpc/platforms/cell/spufs/file.c22
-rw-r--r--arch/powerpc/platforms/cell/spufs/hw_ops.c5
-rw-r--r--arch/powerpc/platforms/cell/spufs/inode.c17
-rw-r--r--arch/powerpc/platforms/cell/spufs/run.c10
-rw-r--r--arch/powerpc/platforms/cell/spufs/spufs.h1
-rw-r--r--arch/powerpc/platforms/cell/spufs/switch.c50
-rw-r--r--include/asm-powerpc/spu.h5
7 files changed, 103 insertions, 7 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
1535struct 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
220static void spu_hw_runcntl_write(struct spu_context *ctx, u32 val) 220static 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
226static void spu_hw_runcntl_stop(struct spu_context *ctx) 229static 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)
51static inline int spu_run_init(struct spu_context *ctx, u32 * npc) 51static 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
137extern struct tree_descr spufs_dir_contents[]; 137extern struct tree_descr spufs_dir_contents[];
138extern struct tree_descr spufs_dir_nosched_contents[];
138 139
139/* system call implementation */ 140/* system call implementation */
140long spufs_run_spu(struct file *file, 141long 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
1919static 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 */
1951static 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
1919static void harvest(struct spu_state *prev, struct spu *spu) 1964static 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}
2105EXPORT_SYMBOL_GPL(spu_save); 2151EXPORT_SYMBOL_GPL(spu_save);
2106 2152
diff --git a/include/asm-powerpc/spu.h b/include/asm-powerpc/spu.h
index cac4ad90a1d4..a1cf476c66f5 100644
--- a/include/asm-powerpc/spu.h
+++ b/include/asm-powerpc/spu.h
@@ -181,8 +181,10 @@ extern struct spufs_calls {
181 */ 181 */
182#define SPU_CREATE_EVENTS_ENABLED 0x0001 182#define SPU_CREATE_EVENTS_ENABLED 0x0001
183#define SPU_CREATE_GANG 0x0002 183#define SPU_CREATE_GANG 0x0002
184#define SPU_CREATE_NOSCHED 0x0004
185#define SPU_CREATE_ISOLATE 0x0008
184 186
185#define SPU_CREATE_FLAG_ALL 0x0003 /* mask of all valid flags */ 187#define SPU_CREATE_FLAG_ALL 0x000f /* mask of all valid flags */
186 188
187 189
188#ifdef CONFIG_SPU_FS_MODULE 190#ifdef CONFIG_SPU_FS_MODULE
@@ -276,6 +278,7 @@ struct spu_problem {
276 u32 spu_runcntl_RW; /* 0x401c */ 278 u32 spu_runcntl_RW; /* 0x401c */
277#define SPU_RUNCNTL_STOP 0L 279#define SPU_RUNCNTL_STOP 0L
278#define SPU_RUNCNTL_RUNNABLE 1L 280#define SPU_RUNCNTL_RUNNABLE 1L
281#define SPU_RUNCNTL_ISOLATE 2L
279 u8 pad_0x4020_0x4024[0x4]; /* 0x4020 */ 282 u8 pad_0x4020_0x4024[0x4]; /* 0x4020 */
280 u32 spu_status_R; /* 0x4024 */ 283 u32 spu_status_R; /* 0x4024 */
281#define SPU_STOP_STATUS_SHIFT 16 284#define SPU_STOP_STATUS_SHIFT 16