aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--arch/powerpc/platforms/cell/spu_base.c44
-rw-r--r--arch/powerpc/platforms/cell/spufs/fault.c10
-rw-r--r--arch/powerpc/platforms/cell/spufs/run.c3
-rw-r--r--arch/powerpc/platforms/cell/spufs/sched.c10
-rw-r--r--arch/powerpc/platforms/cell/spufs/spufs.h13
-rw-r--r--include/asm-powerpc/spu.h17
6 files changed, 95 insertions, 2 deletions
diff --git a/arch/powerpc/platforms/cell/spu_base.c b/arch/powerpc/platforms/cell/spu_base.c
index 174bd9f911db..e4d0c9f42abd 100644
--- a/arch/powerpc/platforms/cell/spu_base.c
+++ b/arch/powerpc/platforms/cell/spu_base.c
@@ -585,6 +585,9 @@ static int __init create_spu(void *data)
585 spin_unlock_irqrestore(&spu_list_lock, flags); 585 spin_unlock_irqrestore(&spu_list_lock, flags);
586 mutex_unlock(&spu_mutex); 586 mutex_unlock(&spu_mutex);
587 587
588 spu->stats.utilization_state = SPU_UTIL_IDLE;
589 spu->stats.tstamp = jiffies;
590
588 goto out; 591 goto out;
589 592
590out_free_irqs: 593out_free_irqs:
@@ -597,6 +600,45 @@ out:
597 return ret; 600 return ret;
598} 601}
599 602
603static const char *spu_state_names[] = {
604 "user", "system", "iowait", "idle"
605};
606
607static unsigned long long spu_acct_time(struct spu *spu,
608 enum spu_utilization_state state)
609{
610 unsigned long long time = spu->stats.times[state];
611
612 if (spu->stats.utilization_state == state)
613 time += jiffies - spu->stats.tstamp;
614
615 return jiffies_to_msecs(time);
616}
617
618
619static ssize_t spu_stat_show(struct sys_device *sysdev, char *buf)
620{
621 struct spu *spu = container_of(sysdev, struct spu, sysdev);
622
623 return sprintf(buf, "%s %llu %llu %llu %llu "
624 "%llu %llu %llu %llu %llu %llu %llu %llu\n",
625 spu_state_names[spu->stats.utilization_state],
626 spu_acct_time(spu, SPU_UTIL_USER),
627 spu_acct_time(spu, SPU_UTIL_SYSTEM),
628 spu_acct_time(spu, SPU_UTIL_IOWAIT),
629 spu_acct_time(spu, SPU_UTIL_IDLE),
630 spu->stats.vol_ctx_switch,
631 spu->stats.invol_ctx_switch,
632 spu->stats.slb_flt,
633 spu->stats.hash_flt,
634 spu->stats.min_flt,
635 spu->stats.maj_flt,
636 spu->stats.class2_intr,
637 spu->stats.libassist);
638}
639
640static SYSDEV_ATTR(stat, 0644, spu_stat_show, NULL);
641
600static int __init init_spu_base(void) 642static int __init init_spu_base(void)
601{ 643{
602 int i, ret = 0; 644 int i, ret = 0;
@@ -622,6 +664,8 @@ static int __init init_spu_base(void)
622 664
623 xmon_register_spus(&spu_full_list); 665 xmon_register_spus(&spu_full_list);
624 666
667 spu_add_sysdev_attr(&attr_stat);
668
625 return 0; 669 return 0;
626 670
627 out_unregister_sysdev_class: 671 out_unregister_sysdev_class:
diff --git a/arch/powerpc/platforms/cell/spufs/fault.c b/arch/powerpc/platforms/cell/spufs/fault.c
index 3a9e49a24ec0..e064d0c0d80e 100644
--- a/arch/powerpc/platforms/cell/spufs/fault.c
+++ b/arch/powerpc/platforms/cell/spufs/fault.c
@@ -187,6 +187,10 @@ int spufs_handle_class1(struct spu_context *ctx)
187 dsisr, ctx->state); 187 dsisr, ctx->state);
188 188
189 ctx->stats.hash_flt++; 189 ctx->stats.hash_flt++;
190 if (ctx->state == SPU_STATE_RUNNABLE) {
191 ctx->spu->stats.hash_flt++;
192 spu_switch_state(ctx->spu, SPU_UTIL_IOWAIT);
193 }
190 194
191 /* we must not hold the lock when entering spu_handle_mm_fault */ 195 /* we must not hold the lock when entering spu_handle_mm_fault */
192 spu_release(ctx); 196 spu_release(ctx);
@@ -212,6 +216,12 @@ int spufs_handle_class1(struct spu_context *ctx)
212 ctx->stats.min_flt++; 216 ctx->stats.min_flt++;
213 else 217 else
214 ctx->stats.maj_flt++; 218 ctx->stats.maj_flt++;
219 if (ctx->state == SPU_STATE_RUNNABLE) {
220 if (flt == VM_FAULT_MINOR)
221 ctx->spu->stats.min_flt++;
222 else
223 ctx->spu->stats.maj_flt++;
224 }
215 225
216 if (ctx->spu) 226 if (ctx->spu)
217 ctx->ops->restart_dma(ctx); 227 ctx->ops->restart_dma(ctx);
diff --git a/arch/powerpc/platforms/cell/spufs/run.c b/arch/powerpc/platforms/cell/spufs/run.c
index 05cf815dbdad..58ae13b7de84 100644
--- a/arch/powerpc/platforms/cell/spufs/run.c
+++ b/arch/powerpc/platforms/cell/spufs/run.c
@@ -352,7 +352,8 @@ long spufs_run_spu(struct file *file, struct spu_context *ctx,
352 SPU_STATUS_SINGLE_STEP))); 352 SPU_STATUS_SINGLE_STEP)));
353 353
354 if ((status & SPU_STATUS_STOPPED_BY_STOP) && 354 if ((status & SPU_STATUS_STOPPED_BY_STOP) &&
355 (((status >> SPU_STOP_STATUS_SHIFT) & 0x3f00) == 0x2100)) 355 (((status >> SPU_STOP_STATUS_SHIFT) & 0x3f00) == 0x2100) &&
356 (ctx->state == SPU_STATE_RUNNABLE))
356 ctx->stats.libassist++; 357 ctx->stats.libassist++;
357 358
358 ctx->ops->master_stop(ctx); 359 ctx->ops->master_stop(ctx);
diff --git a/arch/powerpc/platforms/cell/spufs/sched.c b/arch/powerpc/platforms/cell/spufs/sched.c
index 9fb3133268f6..e5b4dd1db286 100644
--- a/arch/powerpc/platforms/cell/spufs/sched.c
+++ b/arch/powerpc/platforms/cell/spufs/sched.c
@@ -251,6 +251,7 @@ static void spu_bind_context(struct spu *spu, struct spu_context *ctx)
251 spu_cpu_affinity_set(spu, raw_smp_processor_id()); 251 spu_cpu_affinity_set(spu, raw_smp_processor_id());
252 spu_switch_notify(spu, ctx); 252 spu_switch_notify(spu, ctx);
253 ctx->state = SPU_STATE_RUNNABLE; 253 ctx->state = SPU_STATE_RUNNABLE;
254 spu_switch_state(spu, SPU_UTIL_SYSTEM);
254} 255}
255 256
256/** 257/**
@@ -263,6 +264,8 @@ static void spu_unbind_context(struct spu *spu, struct spu_context *ctx)
263 pr_debug("%s: unbind pid=%d SPU=%d NODE=%d\n", __FUNCTION__, 264 pr_debug("%s: unbind pid=%d SPU=%d NODE=%d\n", __FUNCTION__,
264 spu->pid, spu->number, spu->node); 265 spu->pid, spu->number, spu->node);
265 266
267 spu_switch_state(spu, SPU_UTIL_IDLE);
268
266 spu_switch_notify(spu, NULL); 269 spu_switch_notify(spu, NULL);
267 spu_unmap_mappings(ctx); 270 spu_unmap_mappings(ctx);
268 spu_save(&ctx->csa, spu); 271 spu_save(&ctx->csa, spu);
@@ -426,6 +429,7 @@ static struct spu *find_victim(struct spu_context *ctx)
426 spu_remove_from_active_list(spu); 429 spu_remove_from_active_list(spu);
427 spu_unbind_context(spu, victim); 430 spu_unbind_context(spu, victim);
428 victim->stats.invol_ctx_switch++; 431 victim->stats.invol_ctx_switch++;
432 spu->stats.invol_ctx_switch++;
429 mutex_unlock(&victim->state_mutex); 433 mutex_unlock(&victim->state_mutex);
430 /* 434 /*
431 * We need to break out of the wait loop in spu_run 435 * We need to break out of the wait loop in spu_run
@@ -526,6 +530,7 @@ static int __spu_deactivate(struct spu_context *ctx, int force, int max_prio)
526 spu_remove_from_active_list(spu); 530 spu_remove_from_active_list(spu);
527 spu_unbind_context(spu, ctx); 531 spu_unbind_context(spu, ctx);
528 ctx->stats.vol_ctx_switch++; 532 ctx->stats.vol_ctx_switch++;
533 spu->stats.vol_ctx_switch++;
529 spu_free(spu); 534 spu_free(spu);
530 if (new) 535 if (new)
531 wake_up(&new->stop_wq); 536 wake_up(&new->stop_wq);
@@ -572,8 +577,10 @@ void spu_yield(struct spu_context *ctx)
572 mutex_lock(&ctx->state_mutex); 577 mutex_lock(&ctx->state_mutex);
573 if (__spu_deactivate(ctx, 0, MAX_PRIO)) 578 if (__spu_deactivate(ctx, 0, MAX_PRIO))
574 spuctx_switch_state(ctx, SPUCTX_UTIL_USER); 579 spuctx_switch_state(ctx, SPUCTX_UTIL_USER);
575 else 580 else {
576 spuctx_switch_state(ctx, SPUCTX_UTIL_LOADED); 581 spuctx_switch_state(ctx, SPUCTX_UTIL_LOADED);
582 spu_switch_state(ctx->spu, SPU_UTIL_USER);
583 }
577 mutex_unlock(&ctx->state_mutex); 584 mutex_unlock(&ctx->state_mutex);
578 } 585 }
579} 586}
@@ -603,6 +610,7 @@ static void spusched_tick(struct spu_context *ctx)
603 __spu_remove_from_active_list(spu); 610 __spu_remove_from_active_list(spu);
604 spu_unbind_context(spu, ctx); 611 spu_unbind_context(spu, ctx);
605 ctx->stats.invol_ctx_switch++; 612 ctx->stats.invol_ctx_switch++;
613 spu->stats.invol_ctx_switch++;
606 spu_free(spu); 614 spu_free(spu);
607 wake_up(&new->stop_wq); 615 wake_up(&new->stop_wq);
608 /* 616 /*
diff --git a/arch/powerpc/platforms/cell/spufs/spufs.h b/arch/powerpc/platforms/cell/spufs/spufs.h
index cd2b54f6e378..08b3530288ac 100644
--- a/arch/powerpc/platforms/cell/spufs/spufs.h
+++ b/arch/powerpc/platforms/cell/spufs/spufs.h
@@ -307,4 +307,17 @@ static inline void spuctx_switch_state(struct spu_context *ctx,
307 } 307 }
308} 308}
309 309
310static inline void spu_switch_state(struct spu *spu,
311 enum spuctx_execution_state new_state)
312{
313 if (spu->stats.utilization_state != new_state) {
314 unsigned long curtime = jiffies;
315
316 spu->stats.times[spu->stats.utilization_state] +=
317 curtime - spu->stats.tstamp;
318 spu->stats.tstamp = curtime;
319 spu->stats.utilization_state = new_state;
320 }
321}
322
310#endif 323#endif
diff --git a/include/asm-powerpc/spu.h b/include/asm-powerpc/spu.h
index 5957fcdda04c..eedc828cef2d 100644
--- a/include/asm-powerpc/spu.h
+++ b/include/asm-powerpc/spu.h
@@ -106,6 +106,14 @@ struct spu_context;
106struct spu_runqueue; 106struct spu_runqueue;
107struct device_node; 107struct device_node;
108 108
109enum spu_utilization_state {
110 SPU_UTIL_SYSTEM,
111 SPU_UTIL_USER,
112 SPU_UTIL_IOWAIT,
113 SPU_UTIL_IDLE,
114 SPU_UTIL_MAX
115};
116
109struct spu { 117struct spu {
110 const char *name; 118 const char *name;
111 unsigned long local_store_phys; 119 unsigned long local_store_phys;
@@ -159,8 +167,17 @@ struct spu {
159 167
160 struct { 168 struct {
161 /* protected by interrupt reentrancy */ 169 /* protected by interrupt reentrancy */
170 enum spu_utilization_state utilization_state;
171 unsigned long tstamp; /* time of last ctx switch */
172 unsigned long times[SPU_UTIL_MAX];
173 unsigned long long vol_ctx_switch;
174 unsigned long long invol_ctx_switch;
175 unsigned long long min_flt;
176 unsigned long long maj_flt;
177 unsigned long long hash_flt;
162 unsigned long long slb_flt; 178 unsigned long long slb_flt;
163 unsigned long long class2_intr; 179 unsigned long long class2_intr;
180 unsigned long long libassist;
164 } stats; 181 } stats;
165}; 182};
166 183