diff options
Diffstat (limited to 'arch/powerpc')
-rw-r--r-- | arch/powerpc/platforms/cell/spufs/sched.c | 98 |
1 files changed, 61 insertions, 37 deletions
diff --git a/arch/powerpc/platforms/cell/spufs/sched.c b/arch/powerpc/platforms/cell/spufs/sched.c index 7e9657eb690c..1d330f67f5ae 100644 --- a/arch/powerpc/platforms/cell/spufs/sched.c +++ b/arch/powerpc/platforms/cell/spufs/sched.c | |||
@@ -68,6 +68,43 @@ static inline int node_allowed(int node) | |||
68 | return 1; | 68 | return 1; |
69 | } | 69 | } |
70 | 70 | ||
71 | /** | ||
72 | * spu_add_to_active_list - add spu to active list | ||
73 | * @spu: spu to add to the active list | ||
74 | */ | ||
75 | static void spu_add_to_active_list(struct spu *spu) | ||
76 | { | ||
77 | mutex_lock(&spu_prio->active_mutex[spu->node]); | ||
78 | list_add_tail(&spu->list, &spu_prio->active_list[spu->node]); | ||
79 | mutex_unlock(&spu_prio->active_mutex[spu->node]); | ||
80 | } | ||
81 | |||
82 | /** | ||
83 | * spu_remove_from_active_list - remove spu from active list | ||
84 | * @spu: spu to remove from the active list | ||
85 | * | ||
86 | * This function removes an spu from the active list. If the spu was | ||
87 | * found on the active list the function returns 1, else it doesn't do | ||
88 | * anything and returns 0. | ||
89 | */ | ||
90 | static int spu_remove_from_active_list(struct spu *spu) | ||
91 | { | ||
92 | int node = spu->node; | ||
93 | struct spu *tmp; | ||
94 | int rc = 0; | ||
95 | |||
96 | mutex_lock(&spu_prio->active_mutex[node]); | ||
97 | list_for_each_entry(tmp, &spu_prio->active_list[node], list) { | ||
98 | if (tmp == spu) { | ||
99 | list_del_init(&spu->list); | ||
100 | rc = 1; | ||
101 | break; | ||
102 | } | ||
103 | } | ||
104 | mutex_unlock(&spu_prio->active_mutex[node]); | ||
105 | return rc; | ||
106 | } | ||
107 | |||
71 | static inline void mm_needs_global_tlbie(struct mm_struct *mm) | 108 | static inline void mm_needs_global_tlbie(struct mm_struct *mm) |
72 | { | 109 | { |
73 | int nr = (NR_CPUS > 1) ? NR_CPUS : NR_CPUS + 1; | 110 | int nr = (NR_CPUS > 1) ? NR_CPUS : NR_CPUS + 1; |
@@ -94,8 +131,12 @@ int spu_switch_event_unregister(struct notifier_block * n) | |||
94 | return blocking_notifier_chain_unregister(&spu_switch_notifier, n); | 131 | return blocking_notifier_chain_unregister(&spu_switch_notifier, n); |
95 | } | 132 | } |
96 | 133 | ||
97 | 134 | /** | |
98 | static inline void bind_context(struct spu *spu, struct spu_context *ctx) | 135 | * spu_bind_context - bind spu context to physical spu |
136 | * @spu: physical spu to bind to | ||
137 | * @ctx: context to bind | ||
138 | */ | ||
139 | static void spu_bind_context(struct spu *spu, struct spu_context *ctx) | ||
99 | { | 140 | { |
100 | pr_debug("%s: pid=%d SPU=%d NODE=%d\n", __FUNCTION__, current->pid, | 141 | pr_debug("%s: pid=%d SPU=%d NODE=%d\n", __FUNCTION__, current->pid, |
101 | spu->number, spu->node); | 142 | spu->number, spu->node); |
@@ -118,14 +159,24 @@ static inline void bind_context(struct spu *spu, struct spu_context *ctx) | |||
118 | spu->timestamp = jiffies; | 159 | spu->timestamp = jiffies; |
119 | spu_cpu_affinity_set(spu, raw_smp_processor_id()); | 160 | spu_cpu_affinity_set(spu, raw_smp_processor_id()); |
120 | spu_switch_notify(spu, ctx); | 161 | spu_switch_notify(spu, ctx); |
121 | 162 | spu_add_to_active_list(spu); | |
122 | ctx->state = SPU_STATE_RUNNABLE; | 163 | ctx->state = SPU_STATE_RUNNABLE; |
123 | } | 164 | } |
124 | 165 | ||
125 | static inline void unbind_context(struct spu *spu, struct spu_context *ctx) | 166 | /** |
167 | * spu_unbind_context - unbind spu context from physical spu | ||
168 | * @spu: physical spu to unbind from | ||
169 | * @ctx: context to unbind | ||
170 | * | ||
171 | * If the spu was on the active list the function returns 1, else 0. | ||
172 | */ | ||
173 | static int spu_unbind_context(struct spu *spu, struct spu_context *ctx) | ||
126 | { | 174 | { |
175 | int was_active = spu_remove_from_active_list(spu); | ||
176 | |||
127 | pr_debug("%s: unbind pid=%d SPU=%d NODE=%d\n", __FUNCTION__, | 177 | pr_debug("%s: unbind pid=%d SPU=%d NODE=%d\n", __FUNCTION__, |
128 | spu->pid, spu->number, spu->node); | 178 | spu->pid, spu->number, spu->node); |
179 | |||
129 | spu_switch_notify(spu, NULL); | 180 | spu_switch_notify(spu, NULL); |
130 | spu_unmap_mappings(ctx); | 181 | spu_unmap_mappings(ctx); |
131 | spu_save(&ctx->csa, spu); | 182 | spu_save(&ctx->csa, spu); |
@@ -143,6 +194,8 @@ static inline void unbind_context(struct spu *spu, struct spu_context *ctx) | |||
143 | ctx->spu = NULL; | 194 | ctx->spu = NULL; |
144 | spu->flags = 0; | 195 | spu->flags = 0; |
145 | spu->ctx = NULL; | 196 | spu->ctx = NULL; |
197 | |||
198 | return was_active; | ||
146 | } | 199 | } |
147 | 200 | ||
148 | static inline void spu_add_wq(wait_queue_head_t * wq, wait_queue_t * wait, | 201 | static inline void spu_add_wq(wait_queue_head_t * wq, wait_queue_t * wait, |
@@ -199,33 +252,6 @@ static void spu_prio_wakeup(void) | |||
199 | } | 252 | } |
200 | } | 253 | } |
201 | 254 | ||
202 | static int get_active_spu(struct spu *spu) | ||
203 | { | ||
204 | int node = spu->node; | ||
205 | struct spu *tmp; | ||
206 | int rc = 0; | ||
207 | |||
208 | mutex_lock(&spu_prio->active_mutex[node]); | ||
209 | list_for_each_entry(tmp, &spu_prio->active_list[node], list) { | ||
210 | if (tmp == spu) { | ||
211 | list_del_init(&spu->list); | ||
212 | rc = 1; | ||
213 | break; | ||
214 | } | ||
215 | } | ||
216 | mutex_unlock(&spu_prio->active_mutex[node]); | ||
217 | return rc; | ||
218 | } | ||
219 | |||
220 | static void put_active_spu(struct spu *spu) | ||
221 | { | ||
222 | int node = spu->node; | ||
223 | |||
224 | mutex_lock(&spu_prio->active_mutex[node]); | ||
225 | list_add_tail(&spu->list, &spu_prio->active_list[node]); | ||
226 | mutex_unlock(&spu_prio->active_mutex[node]); | ||
227 | } | ||
228 | |||
229 | static struct spu *spu_get_idle(struct spu_context *ctx, u64 flags) | 255 | static struct spu *spu_get_idle(struct spu_context *ctx, u64 flags) |
230 | { | 256 | { |
231 | struct spu *spu = NULL; | 257 | struct spu *spu = NULL; |
@@ -275,8 +301,7 @@ int spu_activate(struct spu_context *ctx, u64 flags) | |||
275 | spu_prio_wakeup(); | 301 | spu_prio_wakeup(); |
276 | break; | 302 | break; |
277 | } | 303 | } |
278 | bind_context(spu, ctx); | 304 | spu_bind_context(spu, ctx); |
279 | put_active_spu(spu); | ||
280 | break; | 305 | break; |
281 | } | 306 | } |
282 | spu_prio_wait(ctx, flags); | 307 | spu_prio_wait(ctx, flags); |
@@ -292,14 +317,13 @@ int spu_activate(struct spu_context *ctx, u64 flags) | |||
292 | void spu_deactivate(struct spu_context *ctx) | 317 | void spu_deactivate(struct spu_context *ctx) |
293 | { | 318 | { |
294 | struct spu *spu; | 319 | struct spu *spu; |
295 | int needs_idle; | 320 | int was_active; |
296 | 321 | ||
297 | spu = ctx->spu; | 322 | spu = ctx->spu; |
298 | if (!spu) | 323 | if (!spu) |
299 | return; | 324 | return; |
300 | needs_idle = get_active_spu(spu); | 325 | was_active = spu_unbind_context(spu, ctx); |
301 | unbind_context(spu, ctx); | 326 | if (was_active) { |
302 | if (needs_idle) { | ||
303 | spu_free(spu); | 327 | spu_free(spu); |
304 | spu_prio_wakeup(); | 328 | spu_prio_wakeup(); |
305 | } | 329 | } |