aboutsummaryrefslogtreecommitdiff
path: root/arch/powerpc/platforms/cell/spu_base.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/powerpc/platforms/cell/spu_base.c')
-rw-r--r--arch/powerpc/platforms/cell/spu_base.c59
1 files changed, 57 insertions, 2 deletions
diff --git a/arch/powerpc/platforms/cell/spu_base.c b/arch/powerpc/platforms/cell/spu_base.c
index a7f5a7653c6..e4d0c9f42ab 100644
--- a/arch/powerpc/platforms/cell/spu_base.c
+++ b/arch/powerpc/platforms/cell/spu_base.c
@@ -183,7 +183,7 @@ static int __spu_trap_data_seg(struct spu *spu, unsigned long ea)
spu->slb_replace = 0;
spu_restart_dma(spu);
-
+ spu->stats.slb_flt++;
return 0;
}
@@ -332,6 +332,7 @@ spu_irq_class_2(int irq, void *data)
if (stat & 0x10) /* SPU mailbox threshold */
spu->wbox_callback(spu);
+ spu->stats.class2_intr++;
return stat ? IRQ_HANDLED : IRQ_NONE;
}
@@ -462,8 +463,18 @@ void spu_free(struct spu *spu)
}
EXPORT_SYMBOL_GPL(spu_free);
+static int spu_shutdown(struct sys_device *sysdev)
+{
+ struct spu *spu = container_of(sysdev, struct spu, sysdev);
+
+ spu_free_irqs(spu);
+ spu_destroy_spu(spu);
+ return 0;
+}
+
struct sysdev_class spu_sysdev_class = {
- set_kset_name("spu")
+ set_kset_name("spu"),
+ .shutdown = spu_shutdown,
};
int spu_add_sysdev_attr(struct sysdev_attribute *attr)
@@ -574,6 +585,9 @@ static int __init create_spu(void *data)
spin_unlock_irqrestore(&spu_list_lock, flags);
mutex_unlock(&spu_mutex);
+ spu->stats.utilization_state = SPU_UTIL_IDLE;
+ spu->stats.tstamp = jiffies;
+
goto out;
out_free_irqs:
@@ -586,6 +600,45 @@ out:
return ret;
}
+static const char *spu_state_names[] = {
+ "user", "system", "iowait", "idle"
+};
+
+static unsigned long long spu_acct_time(struct spu *spu,
+ enum spu_utilization_state state)
+{
+ unsigned long long time = spu->stats.times[state];
+
+ if (spu->stats.utilization_state == state)
+ time += jiffies - spu->stats.tstamp;
+
+ return jiffies_to_msecs(time);
+}
+
+
+static ssize_t spu_stat_show(struct sys_device *sysdev, char *buf)
+{
+ struct spu *spu = container_of(sysdev, struct spu, sysdev);
+
+ return sprintf(buf, "%s %llu %llu %llu %llu "
+ "%llu %llu %llu %llu %llu %llu %llu %llu\n",
+ spu_state_names[spu->stats.utilization_state],
+ spu_acct_time(spu, SPU_UTIL_USER),
+ spu_acct_time(spu, SPU_UTIL_SYSTEM),
+ spu_acct_time(spu, SPU_UTIL_IOWAIT),
+ spu_acct_time(spu, SPU_UTIL_IDLE),
+ spu->stats.vol_ctx_switch,
+ spu->stats.invol_ctx_switch,
+ spu->stats.slb_flt,
+ spu->stats.hash_flt,
+ spu->stats.min_flt,
+ spu->stats.maj_flt,
+ spu->stats.class2_intr,
+ spu->stats.libassist);
+}
+
+static SYSDEV_ATTR(stat, 0644, spu_stat_show, NULL);
+
static int __init init_spu_base(void)
{
int i, ret = 0;
@@ -611,6 +664,8 @@ static int __init init_spu_base(void)
xmon_register_spus(&spu_full_list);
+ spu_add_sysdev_attr(&attr_stat);
+
return 0;
out_unregister_sysdev_class: