aboutsummaryrefslogtreecommitdiffstats
path: root/arch/powerpc
diff options
context:
space:
mode:
authorChristoph Hellwig <hch@lst.de>2007-06-28 20:58:07 -0400
committerPaul Mackerras <paulus@samba.org>2007-07-03 01:24:46 -0400
commitfe2f896d67b89a409c366c9a69e30291ab124467 (patch)
treedf0cc1fa1923f03b90920dd399640e7b462a8171 /arch/powerpc
parent27449971e6907ff38bde7bbc4647e55bd7309fc3 (diff)
[POWERPC] spufs: Add spu stats in sysfs
Export spu statistics in sysfs. Signed-off-by: Christoph Hellwig <hch@lst.de> Signed-off-by: Arnd Bergmann <arnd.bergmann@de.ibm.com> Signed-off-by: Jeremy Kerr <jk@ozlabs.org> Signed-off-by: Paul Mackerras <paulus@samba.org>
Diffstat (limited to 'arch/powerpc')
-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
5 files changed, 78 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