diff options
Diffstat (limited to 'arch/powerpc')
-rw-r--r-- | arch/powerpc/platforms/cell/spufs/context.c | 2 | ||||
-rw-r--r-- | arch/powerpc/platforms/cell/spufs/run.c | 9 | ||||
-rw-r--r-- | arch/powerpc/platforms/cell/spufs/sched.c | 43 | ||||
-rw-r--r-- | arch/powerpc/platforms/cell/spufs/spufs.h | 5 |
4 files changed, 56 insertions, 3 deletions
diff --git a/arch/powerpc/platforms/cell/spufs/context.c b/arch/powerpc/platforms/cell/spufs/context.c index d581f4ec99ba..04ad2e364e97 100644 --- a/arch/powerpc/platforms/cell/spufs/context.c +++ b/arch/powerpc/platforms/cell/spufs/context.c | |||
@@ -54,7 +54,9 @@ struct spu_context *alloc_spu_context(struct spu_gang *gang) | |||
54 | if (gang) | 54 | if (gang) |
55 | spu_gang_add_ctx(gang, ctx); | 55 | spu_gang_add_ctx(gang, ctx); |
56 | ctx->rt_priority = current->rt_priority; | 56 | ctx->rt_priority = current->rt_priority; |
57 | ctx->policy = current->policy; | ||
57 | ctx->prio = current->prio; | 58 | ctx->prio = current->prio; |
59 | INIT_DELAYED_WORK(&ctx->sched_work, spu_sched_tick); | ||
58 | goto out; | 60 | goto out; |
59 | out_free: | 61 | out_free: |
60 | kfree(ctx); | 62 | kfree(ctx); |
diff --git a/arch/powerpc/platforms/cell/spufs/run.c b/arch/powerpc/platforms/cell/spufs/run.c index a973e79e9fdc..353a8fa07ab8 100644 --- a/arch/powerpc/platforms/cell/spufs/run.c +++ b/arch/powerpc/platforms/cell/spufs/run.c | |||
@@ -164,8 +164,10 @@ static inline int spu_run_init(struct spu_context *ctx, u32 * npc) | |||
164 | (SPU_RUNCNTL_RUNNABLE | SPU_RUNCNTL_ISOLATE); | 164 | (SPU_RUNCNTL_RUNNABLE | SPU_RUNCNTL_ISOLATE); |
165 | if (runcntl == 0) | 165 | if (runcntl == 0) |
166 | runcntl = SPU_RUNCNTL_RUNNABLE; | 166 | runcntl = SPU_RUNCNTL_RUNNABLE; |
167 | } else | 167 | } else { |
168 | spu_start_tick(ctx); | ||
168 | ctx->ops->npc_write(ctx, *npc); | 169 | ctx->ops->npc_write(ctx, *npc); |
170 | } | ||
169 | 171 | ||
170 | ctx->ops->runcntl_write(ctx, runcntl); | 172 | ctx->ops->runcntl_write(ctx, runcntl); |
171 | return ret; | 173 | return ret; |
@@ -176,6 +178,7 @@ static inline int spu_run_fini(struct spu_context *ctx, u32 * npc, | |||
176 | { | 178 | { |
177 | int ret = 0; | 179 | int ret = 0; |
178 | 180 | ||
181 | spu_stop_tick(ctx); | ||
179 | *status = ctx->ops->status_read(ctx); | 182 | *status = ctx->ops->status_read(ctx); |
180 | *npc = ctx->ops->npc_read(ctx); | 183 | *npc = ctx->ops->npc_read(ctx); |
181 | spu_release(ctx); | 184 | spu_release(ctx); |
@@ -329,8 +332,10 @@ long spufs_run_spu(struct file *file, struct spu_context *ctx, | |||
329 | } | 332 | } |
330 | if (unlikely(ctx->state != SPU_STATE_RUNNABLE)) { | 333 | if (unlikely(ctx->state != SPU_STATE_RUNNABLE)) { |
331 | ret = spu_reacquire_runnable(ctx, npc, &status); | 334 | ret = spu_reacquire_runnable(ctx, npc, &status); |
332 | if (ret) | 335 | if (ret) { |
336 | spu_stop_tick(ctx); | ||
333 | goto out2; | 337 | goto out2; |
338 | } | ||
334 | continue; | 339 | continue; |
335 | } | 340 | } |
336 | ret = spu_process_events(ctx); | 341 | ret = spu_process_events(ctx); |
diff --git a/arch/powerpc/platforms/cell/spufs/sched.c b/arch/powerpc/platforms/cell/spufs/sched.c index ba4b01e01ace..2f25e68b4bac 100644 --- a/arch/powerpc/platforms/cell/spufs/sched.c +++ b/arch/powerpc/platforms/cell/spufs/sched.c | |||
@@ -44,7 +44,7 @@ | |||
44 | #include <asm/spu_priv1.h> | 44 | #include <asm/spu_priv1.h> |
45 | #include "spufs.h" | 45 | #include "spufs.h" |
46 | 46 | ||
47 | #define SPU_MIN_TIMESLICE (100 * HZ / 1000) | 47 | #define SPU_TIMESLICE (HZ) |
48 | 48 | ||
49 | struct spu_prio_array { | 49 | struct spu_prio_array { |
50 | DECLARE_BITMAP(bitmap, MAX_PRIO); | 50 | DECLARE_BITMAP(bitmap, MAX_PRIO); |
@@ -55,6 +55,7 @@ struct spu_prio_array { | |||
55 | }; | 55 | }; |
56 | 56 | ||
57 | static struct spu_prio_array *spu_prio; | 57 | static struct spu_prio_array *spu_prio; |
58 | static struct workqueue_struct *spu_sched_wq; | ||
58 | 59 | ||
59 | static inline int node_allowed(int node) | 60 | static inline int node_allowed(int node) |
60 | { | 61 | { |
@@ -68,6 +69,40 @@ static inline int node_allowed(int node) | |||
68 | return 1; | 69 | return 1; |
69 | } | 70 | } |
70 | 71 | ||
72 | void spu_start_tick(struct spu_context *ctx) | ||
73 | { | ||
74 | if (ctx->policy == SCHED_RR) | ||
75 | queue_delayed_work(spu_sched_wq, &ctx->sched_work, SPU_TIMESLICE); | ||
76 | } | ||
77 | |||
78 | void spu_stop_tick(struct spu_context *ctx) | ||
79 | { | ||
80 | if (ctx->policy == SCHED_RR) | ||
81 | cancel_delayed_work(&ctx->sched_work); | ||
82 | } | ||
83 | |||
84 | void spu_sched_tick(struct work_struct *work) | ||
85 | { | ||
86 | struct spu_context *ctx = | ||
87 | container_of(work, struct spu_context, sched_work.work); | ||
88 | struct spu *spu; | ||
89 | int rearm = 1; | ||
90 | |||
91 | mutex_lock(&ctx->state_mutex); | ||
92 | spu = ctx->spu; | ||
93 | if (spu) { | ||
94 | int best = sched_find_first_bit(spu_prio->bitmap); | ||
95 | if (best <= ctx->prio) { | ||
96 | spu_deactivate(ctx); | ||
97 | rearm = 0; | ||
98 | } | ||
99 | } | ||
100 | mutex_unlock(&ctx->state_mutex); | ||
101 | |||
102 | if (rearm) | ||
103 | spu_start_tick(ctx); | ||
104 | } | ||
105 | |||
71 | /** | 106 | /** |
72 | * spu_add_to_active_list - add spu to active list | 107 | * spu_add_to_active_list - add spu to active list |
73 | * @spu: spu to add to the active list | 108 | * @spu: spu to add to the active list |
@@ -437,10 +472,15 @@ int __init spu_sched_init(void) | |||
437 | { | 472 | { |
438 | int i; | 473 | int i; |
439 | 474 | ||
475 | spu_sched_wq = create_singlethread_workqueue("spusched"); | ||
476 | if (!spu_sched_wq) | ||
477 | return 1; | ||
478 | |||
440 | spu_prio = kzalloc(sizeof(struct spu_prio_array), GFP_KERNEL); | 479 | spu_prio = kzalloc(sizeof(struct spu_prio_array), GFP_KERNEL); |
441 | if (!spu_prio) { | 480 | if (!spu_prio) { |
442 | printk(KERN_WARNING "%s: Unable to allocate priority queue.\n", | 481 | printk(KERN_WARNING "%s: Unable to allocate priority queue.\n", |
443 | __FUNCTION__); | 482 | __FUNCTION__); |
483 | destroy_workqueue(spu_sched_wq); | ||
444 | return 1; | 484 | return 1; |
445 | } | 485 | } |
446 | for (i = 0; i < MAX_PRIO; i++) { | 486 | for (i = 0; i < MAX_PRIO; i++) { |
@@ -471,4 +511,5 @@ void __exit spu_sched_exit(void) | |||
471 | mutex_unlock(&spu_prio->active_mutex[node]); | 511 | mutex_unlock(&spu_prio->active_mutex[node]); |
472 | } | 512 | } |
473 | kfree(spu_prio); | 513 | kfree(spu_prio); |
514 | destroy_workqueue(spu_sched_wq); | ||
474 | } | 515 | } |
diff --git a/arch/powerpc/platforms/cell/spufs/spufs.h b/arch/powerpc/platforms/cell/spufs/spufs.h index 85b182d16464..0c437891dfd5 100644 --- a/arch/powerpc/platforms/cell/spufs/spufs.h +++ b/arch/powerpc/platforms/cell/spufs/spufs.h | |||
@@ -82,8 +82,10 @@ struct spu_context { | |||
82 | 82 | ||
83 | /* scheduler fields */ | 83 | /* scheduler fields */ |
84 | struct list_head rq; | 84 | struct list_head rq; |
85 | struct delayed_work sched_work; | ||
85 | unsigned long sched_flags; | 86 | unsigned long sched_flags; |
86 | unsigned long rt_priority; | 87 | unsigned long rt_priority; |
88 | int policy; | ||
87 | int prio; | 89 | int prio; |
88 | }; | 90 | }; |
89 | 91 | ||
@@ -195,6 +197,9 @@ enum { | |||
195 | int spu_activate(struct spu_context *ctx, unsigned long flags); | 197 | int spu_activate(struct spu_context *ctx, unsigned long flags); |
196 | void spu_deactivate(struct spu_context *ctx); | 198 | void spu_deactivate(struct spu_context *ctx); |
197 | void spu_yield(struct spu_context *ctx); | 199 | void spu_yield(struct spu_context *ctx); |
200 | void spu_start_tick(struct spu_context *ctx); | ||
201 | void spu_stop_tick(struct spu_context *ctx); | ||
202 | void spu_sched_tick(struct work_struct *work); | ||
198 | int __init spu_sched_init(void); | 203 | int __init spu_sched_init(void); |
199 | void __exit spu_sched_exit(void); | 204 | void __exit spu_sched_exit(void); |
200 | 205 | ||