summaryrefslogtreecommitdiff
path: root/drivers/misc/tegra-throughput.c
diff options
context:
space:
mode:
authorSimo Melenius <smelenius@nvidia.com>2014-01-21 15:32:56 +0200
committerJuha Tukkinen <jtukkinen@nvidia.com>2014-02-13 01:40:08 -0800
commit60cd9ae2e87b6150f313a3fb695deb9538b7aab5 (patch)
treef20f1038b0cbf4e06feb6144d8defd97f9335426 /drivers/misc/tegra-throughput.c
parent88d88282b178f785f0a499d39a7188405efc0ee3 (diff)
drivers: cpuload and tegra-throughput to publish monotonic counters
- introducing a couple of new nodes: - cpuload has "cpu_usage" which provides per-cpu time/idle/iowait counters instead of recent load - tegra-throughput has "framerate" which provides time and flip counts instead of averaged framerate Bug 1422044 Change-Id: I84d36b9d47a3fc902c70a04b76cf80d8a9a00e08 Signed-off-by: Simo Melenius <smelenius@nvidia.com> Reviewed-on: http://git-master/r/358678 Reviewed-by: Sachin Nikam <snikam@nvidia.com> Reviewed-by: Juha Tukkinen <jtukkinen@nvidia.com>
Diffstat (limited to 'drivers/misc/tegra-throughput.c')
-rw-r--r--drivers/misc/tegra-throughput.c66
1 files changed, 52 insertions, 14 deletions
diff --git a/drivers/misc/tegra-throughput.c b/drivers/misc/tegra-throughput.c
index 384d36ed9ba4..b8db5c185a22 100644
--- a/drivers/misc/tegra-throughput.c
+++ b/drivers/misc/tegra-throughput.c
@@ -44,6 +44,8 @@ static spinlock_t lock;
static int frame_time_sum_init = 1;
static long frame_time_sum; /* used for fps EMA */
+static u64 framecount;
+static u64 frame_timestamp;
static struct work_struct work;
static int throughput_hint;
@@ -75,6 +77,10 @@ static void throughput_flip_callback(void)
ktime_t now;
now = ktime_get();
+ spin_lock(&lock);
+ framecount++;
+ frame_timestamp = ktime_to_us(now);
+ spin_unlock(&lock);
if (last_flip.tv64 != 0) {
timediff = (long) ktime_us_delta(now, last_flip);
@@ -245,30 +251,59 @@ DONE:
static struct global_attr fps_attr = __ATTR(fps, 0444,
show_fps, NULL);
+static ssize_t show_framecount(struct kobject *kobj,
+ struct attribute *attr, char *buf)
+{
+ u64 fcount;
+ u64 fstamp;
+
+ spin_lock(&lock);
+ fcount = framecount;
+ fstamp = frame_timestamp;
+ spin_unlock(&lock);
+
+ return sprintf(buf, "%llu %llu\n",
+ fcount, fstamp);
+}
+
+static struct global_attr framecount_attr = __ATTR(framecount, 0444,
+ show_framecount, NULL);
+
int __init throughput_init_miscdev(void)
{
- int ret;
+ int ret_md, ret_f1, ret_f2;
pr_debug("%s: initializing\n", __func__);
spin_lock_init(&lock);
INIT_WORK(&work, set_throughput_hint);
- ret = misc_register(&throughput_miscdev);
- if (ret) {
- pr_err("can\'t reigster throughput miscdev"
- " (minor %d err %d)\n", TEGRA_THROUGHPUT_MINOR, ret);
- return ret;
- }
+ ret_md = misc_register(&throughput_miscdev);
+ ret_f1 = sysfs_create_file(&throughput_miscdev.this_device->kobj,
+ &fps_attr.attr);
+ ret_f2 = sysfs_create_file(&throughput_miscdev.this_device->kobj,
+ &framecount_attr.attr);
- ret = sysfs_create_file(&throughput_miscdev.this_device->kobj,
- &fps_attr.attr);
- if (ret)
- pr_err("%s: error %d creating sysfs node\n", __func__, ret);
+ if (ret_md == 0 && ret_f1 == 0 && ret_f2 == 0) {
+ tegra_dc_set_flip_callback(throughput_flip_callback);
- tegra_dc_set_flip_callback(throughput_flip_callback);
+ return 0;
+ }
- return 0;
+ if (ret_f2 == 0)
+ sysfs_remove_file(&throughput_miscdev.this_device->kobj,
+ &framecount_attr.attr);
+ if (ret_f1 == 0)
+ sysfs_remove_file(&throughput_miscdev.this_device->kobj,
+ &fps_attr.attr);
+ if (ret_md == 0)
+ misc_deregister(&throughput_miscdev);
+
+ if (ret_md)
+ return ret_md;
+ if (ret_f1)
+ return ret_f1;
+ return ret_f2;
}
module_init(throughput_init_miscdev);
@@ -281,7 +316,10 @@ void __exit throughput_exit_miscdev(void)
cancel_work_sync(&work);
- sysfs_remove_file(&throughput_miscdev.this_device->kobj, &fps_attr.attr);
+ sysfs_remove_file(&throughput_miscdev.this_device->kobj,
+ &framecount_attr.attr);
+ sysfs_remove_file(&throughput_miscdev.this_device->kobj,
+ &fps_attr.attr);
misc_deregister(&throughput_miscdev);
}